<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"yuzhenxin.gitee.io","root":"/","scheme":"Muse","version":"7.8.0","exturl":false,"sidebar":{"position":"right","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":true},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
  </script>

  <meta name="description" content="余振鑫的个人博客">
<meta property="og:type" content="website">
<meta property="og:title" content="余振鑫的Hexo博客">
<meta property="og:url" content="http://yuzhenxin.gitee.io/index.html">
<meta property="og:site_name" content="余振鑫的Hexo博客">
<meta property="og:description" content="余振鑫的个人博客">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="余振鑫">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="http://yuzhenxin.gitee.io/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : true,
    isPost : false,
    lang   : 'zh-CN'
  };
</script>

  <title>余振鑫的Hexo博客</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">余振鑫的Hexo博客</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">计算机笔记</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content index posts-expand">
            
      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://yuzhenxin.gitee.io/2022/01/18/%E4%B8%80%E4%BA%9B%E5%91%BD%E4%BB%A4/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="余振鑫">
      <meta itemprop="description" content="余振鑫的个人博客">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="余振鑫的Hexo博客">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2022/01/18/%E4%B8%80%E4%BA%9B%E5%91%BD%E4%BB%A4/" class="post-title-link" itemprop="url">一些命令</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2022-01-18 00:00:00 / 修改时间：23:10:16" itemprop="dateCreated datePublished" datetime="2022-01-18T00:00:00+08:00">2022-01-18</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="一些命令"><a href="#一些命令" class="headerlink" title="一些命令"></a>一些命令</h1><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">// 找到进程id（PID）</span><br><span class="line">netstat -ano |findstr <span class="string">&quot;端口号&quot;</span></span><br><span class="line"></span><br><span class="line">// 找到进程</span><br><span class="line">tasklist |findstr <span class="string">&quot;进程id号&quot;</span></span><br><span class="line"></span><br><span class="line">// 结束进程</span><br><span class="line">taskkill /f /t /im <span class="string">&quot;进程id或者进程名称&quot;</span></span><br></pre></td></tr></table></figure>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://yuzhenxin.gitee.io/2022/01/10/Python/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="余振鑫">
      <meta itemprop="description" content="余振鑫的个人博客">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="余振鑫的Hexo博客">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2022/01/10/Python/" class="post-title-link" itemprop="url">Python</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2022-01-10 00:00:00" itemprop="dateCreated datePublished" datetime="2022-01-10T00:00:00+08:00">2022-01-10</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2022-01-18 23:09:45" itemprop="dateModified" datetime="2022-01-18T23:09:45+08:00">2022-01-18</time>
              </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="Python"><a href="#Python" class="headerlink" title="Python"></a>Python</h1><h2 id="安装tensorflow-cpu-2-1"><a href="#安装tensorflow-cpu-2-1" class="headerlink" title="安装tensorflow-cpu 2.1"></a>安装tensorflow-cpu 2.1</h2><h3 id="Tips"><a href="#Tips" class="headerlink" title="Tips"></a>Tips</h3><ul>
<li>pip install是在虚拟环境下安装</li>
<li>conda是在全局环境，然后虚拟环境要就复制过去，不会重复下载（类似maven，但不如maven可以全局共享jar包）</li>
</ul>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">// 镜像</span><br><span class="line">conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/</span><br><span class="line">// 在下载时显示使用的源</span><br><span class="line">conda config --<span class="built_in">set</span> show_channel_urls yes</span><br><span class="line"></span><br><span class="line">// 查看环境</span><br><span class="line">conda info --envs</span><br><span class="line">// 安装环境</span><br><span class="line">conda create -n TF2.1 python=3.7</span><br><span class="line">// 激活环境</span><br><span class="line">conda activate TF2.1</span><br><span class="line">// 查看（当前环境中）已安装的 package</span><br><span class="line">conda list</span><br><span class="line"></span><br><span class="line">// 安装Tensorflow2.1 -CPU版本</span><br><span class="line">conda install tensorflow-cpu==2.1.0 -i https://mirrors.aliyun.com/pypi/simple</span><br><span class="line"></span><br><span class="line">// 退出环境</span><br><span class="line">deactivate</span><br><span class="line">// 删除环境</span><br><span class="line">conda remove --name 环境名 --all</span><br></pre></td></tr></table></figure>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://yuzhenxin.gitee.io/2021/02/15/Vue/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="余振鑫">
      <meta itemprop="description" content="余振鑫的个人博客">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="余振鑫的Hexo博客">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/02/15/Vue/" class="post-title-link" itemprop="url">Vue</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-02-15 00:00:00" itemprop="dateCreated datePublished" datetime="2021-02-15T00:00:00+08:00">2021-02-15</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-03-13 14:36:38" itemprop="dateModified" datetime="2021-03-13T14:36:38+08:00">2021-03-13</time>
              </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="Vue"><a href="#Vue" class="headerlink" title="Vue"></a>Vue</h1><p>Vue.js实现了<strong>MVVM</strong>架构，实现数据双向绑定（console控制台可以改变对象数据，页面实时更新）</p>
<p>npm相当于maven，nodejs是运行环境</p>
<h2 id="基础（2-x）"><a href="#基础（2-x）" class="headerlink" title="基础（2.x）"></a>基础（2.x）</h2><h3 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h3><p>JavaScript中数组[]，对象{}。</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">    &#123;&#123;message&#125;&#125;</span><br><span class="line">    <span class="tag">&lt;<span class="name">span</span> <span class="attr">v-bind:title</span>=<span class="string">&quot;message&quot;</span>&gt;</span>鼠标放在这<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--if--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h1</span> <span class="attr">v-if</span>=<span class="string">&quot;ok&quot;</span>&gt;</span>yes<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h1</span> <span class="attr">v-else</span>&gt;</span>no<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">h1</span> <span class="attr">v-if</span>=<span class="string">&quot;type===&#x27;A&#x27;&quot;</span>&gt;</span>A<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h1</span> <span class="attr">v-else-if</span>=<span class="string">&quot;type===&#x27;B&#x27;&quot;</span>&gt;</span>B<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h1</span> <span class="attr">v-else</span>&gt;</span>Others<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--for--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">li</span> <span class="attr">v-for</span>=<span class="string">&quot;(user,index) in users&quot;</span>&gt;</span>&#123;&#123;index&#125;&#125;--&#123;&#123;user.name&#125;&#125;<span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">&lt;!--事件绑定--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">button</span> <span class="attr">v-on:click</span>=<span class="string">&quot;sayHi&quot;</span>&gt;</span>click me<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--导入vue.js--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript">    <span class="keyword">var</span> vm = <span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="javascript">        el: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line">        data: &#123;</span><br><span class="line"><span class="javascript">            message: <span class="string">&quot;hello,vue&quot;</span>,</span></span><br><span class="line"><span class="javascript">            ok: <span class="literal">true</span>,</span></span><br><span class="line"><span class="javascript">            type: <span class="string">&#x27;A&#x27;</span>,</span></span><br><span class="line">            users: [</span><br><span class="line"><span class="javascript">                &#123;<span class="attr">name</span>: <span class="string">&#x27;余振鑫&#x27;</span>&#125;,</span></span><br><span class="line"><span class="javascript">                &#123;<span class="attr">name</span>: <span class="string">&#x27;张三&#x27;</span>&#125;</span></span><br><span class="line">            ]</span><br><span class="line">        &#125;,</span><br><span class="line">        methods:&#123;</span><br><span class="line"><span class="javascript">            sayHi:<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">                alert(<span class="built_in">this</span>.message);</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="双向绑定（v-model）"><a href="#双向绑定（v-model）" class="headerlink" title="双向绑定（v-model）"></a>双向绑定（v-model）</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">v-model</span>=<span class="string">&quot;message&quot;</span>/&gt;</span>&#123;&#123;message&#125;&#125;</span><br><span class="line">    <span class="tag">&lt;<span class="name">br</span>/&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;radio&quot;</span> <span class="attr">v-model</span>=<span class="string">&quot;human&quot;</span> <span class="attr">value</span>=<span class="string">&quot;男人&quot;</span>&gt;</span>男</span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;radio&quot;</span> <span class="attr">v-model</span>=<span class="string">&quot;human&quot;</span> <span class="attr">value</span>=<span class="string">&quot;女人&quot;</span>&gt;</span>女</span><br><span class="line">    <span class="tag">&lt;<span class="name">select</span> <span class="attr">v-model</span>=<span class="string">&quot;human&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">option</span> <span class="attr">value</span>=<span class="string">&quot;&quot;</span> <span class="attr">disabled</span>&gt;</span>---请选择---<span class="tag">&lt;/<span class="name">option</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">option</span>&gt;</span>A<span class="tag">&lt;/<span class="name">option</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">option</span>&gt;</span>B<span class="tag">&lt;/<span class="name">option</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">option</span>&gt;</span>C<span class="tag">&lt;/<span class="name">option</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span>&gt;</span>选中了&#123;&#123;human&#125;&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript">    <span class="keyword">var</span> vm = <span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="javascript">        el: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line">        data: &#123;</span><br><span class="line"><span class="javascript">            message: <span class="string">&quot;我来了&quot;</span>,</span></span><br><span class="line"><span class="javascript">            human: <span class="string">&#x27;&#x27;</span></span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="组件"><a href="#组件" class="headerlink" title="组件"></a>组件</h3><p>props定义<strong>组件的属性</strong>，v-bind将Vue的<strong>data里的数据</strong>和<strong>组件的属性</strong>绑定<strong>（v-bind:props=”data”）</strong></p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">yuzhenxin</span> <span class="attr">v-for</span>=<span class="string">&quot;item in items&quot;</span> <span class="attr">v-bind:content</span>=<span class="string">&quot;item&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">yuzhenxin</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript">    <span class="comment">// 注册组件</span></span></span><br><span class="line"><span class="javascript">    Vue.component(<span class="string">&quot;yuzhenxin&quot;</span>, &#123;</span></span><br><span class="line"><span class="javascript">        props:[<span class="string">&#x27;content&#x27;</span>],</span></span><br><span class="line"><span class="handlebars"><span class="xml">        template: &#x27;<span class="tag">&lt;<span class="name">li</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">content</span>&#125;&#125;</span><span class="xml"><span class="tag">&lt;/<span class="name">li</span>&gt;</span>&#x27;</span></span></span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line"><span class="javascript">    <span class="keyword">var</span> vm = <span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="javascript">        el: <span class="string">&quot;#app&quot;</span>,</span></span><br><span class="line">        data: &#123;</span><br><span class="line"><span class="javascript">            items:[<span class="string">&quot;java&quot;</span>,<span class="string">&quot;c++&quot;</span>,<span class="string">&quot;nodejs&quot;</span>]</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="axios"><a href="#axios" class="headerlink" title="axios"></a>axios</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;vue&quot;</span>&gt;</span></span><br><span class="line">    &#123;&#123;info&#125;&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--导入JS文件--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://unpkg.com/axios/dist/axios.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript">    <span class="keyword">var</span> vm = <span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="javascript">        el: <span class="string">&#x27;#vue&#x27;</span>,</span></span><br><span class="line"><span class="javascript">        <span class="function"><span class="title">data</span>(<span class="params"></span>)</span>&#123;</span></span><br><span class="line"><span class="javascript">            <span class="keyword">return</span> &#123;</span></span><br><span class="line">                info: &#123;&#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;,</span><br><span class="line"><span class="javascript">        <span class="function"><span class="title">mounted</span>(<span class="params"></span>)</span>&#123;</span></span><br><span class="line">            axios</span><br><span class="line"><span class="javascript">                .get(<span class="string">&#x27;../data.json&#x27;</span>)</span></span><br><span class="line"><span class="javascript">                .then(<span class="function"><span class="params">response</span> =&gt;</span> (<span class="built_in">this</span>.info = response.data))</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="计算属性"><a href="#计算属性" class="headerlink" title="计算属性"></a>计算属性</h3><p>类似于MyBatis缓存，将不常变化的计算结果缓存起来。</p>
<p>和methods类比，注意调用的区别</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;vue&quot;</span>&gt;</span></span><br><span class="line">    &#123;&#123;getTime1()&#125;&#125;</span><br><span class="line">    &#123;&#123;getTime2&#125;&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--导入JS文件--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://unpkg.com/axios/dist/axios.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript">    <span class="keyword">var</span> vm = <span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="javascript">        el: <span class="string">&#x27;#vue&#x27;</span>,</span></span><br><span class="line">        data: &#123;</span><br><span class="line"><span class="javascript">            message: <span class="string">&quot;abc&quot;</span></span></span><br><span class="line">        &#125;,</span><br><span class="line">        methods: &#123;</span><br><span class="line"><span class="javascript">            getTime1: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">                <span class="keyword">return</span> <span class="built_in">Date</span>.now();</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;,</span><br><span class="line">        computed: &#123;</span><br><span class="line"><span class="javascript">            getTime2: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">                <span class="built_in">this</span>.message;</span></span><br><span class="line"><span class="javascript">                <span class="keyword">return</span> <span class="built_in">Date</span>.now();</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307223851.png" alt="image-20210224110505679" style="zoom:50%;" />

<h3 id="slot和事件分发"><a href="#slot和事件分发" class="headerlink" title="slot和事件分发"></a>slot和事件分发</h3><p>组件之间通过插槽slot关联，todo组件为螺母，todo-title为螺丝，调用组件时相当于上螺丝</p>
<p>组件 –&gt; 前端  –&gt; vue实例</p>
<p>vue实例的data和methods相当于全局变量，在前端可见，而组件想要获取和使用vue实例的data和methods时需要在前端进行绑定，使用<strong>v-bind:prop=”data”<strong>和</strong>v-on:compMethod = “methods”</strong></p>
<ul>
<li>v-bind简写 ==:==</li>
<li>v-on简写 ==@==</li>
</ul>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;vue&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">todo</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">todo-title</span> <span class="attr">slot</span>=<span class="string">&quot;todo-title&quot;</span> <span class="attr">:title</span>=<span class="string">&quot;titleData&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">todo-title</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">todo-items</span> <span class="attr">slot</span>=<span class="string">&quot;todo-items&quot;</span> <span class="attr">v-for</span>=<span class="string">&quot;(item,index) in itemsData&quot;</span></span></span><br><span class="line"><span class="tag">                    <span class="attr">:item</span>=<span class="string">&quot;item&quot;</span> <span class="attr">v-on:delete1</span>=<span class="string">&quot;deleteItem&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">todo-items</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">todo</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--导入JS文件--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://unpkg.com/axios/dist/axios.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="javascript">    <span class="comment">// 定义组件</span></span></span><br><span class="line"><span class="javascript">    Vue.component(<span class="string">&quot;todo&quot;</span>, &#123;</span></span><br><span class="line">        template:</span><br><span class="line"><span class="handlebars"><span class="xml">            `<span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="handlebars"><span class="xml">            <span class="tag">&lt;<span class="name">slot</span> <span class="attr">name</span>=<span class="string">&quot;todo-title&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span></span></span><br><span class="line"><span class="handlebars"><span class="xml">            <span class="tag">&lt;<span class="name">ul</span>&gt;</span></span></span></span><br><span class="line"><span class="handlebars"><span class="xml">                <span class="tag">&lt;<span class="name">slot</span> <span class="attr">name</span>=<span class="string">&quot;todo-items&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span></span></span><br><span class="line"><span class="handlebars"><span class="xml">            <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span></span></span><br><span class="line"><span class="handlebars"><span class="xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span>`</span></span></span><br><span class="line">    &#125;);</span><br><span class="line"><span class="javascript">    Vue.component(<span class="string">&quot;todo-title&quot;</span>, &#123;</span></span><br><span class="line"><span class="javascript">        props: [<span class="string">&#x27;title&#x27;</span>],</span></span><br><span class="line"><span class="handlebars"><span class="xml">        template: &#x27;<span class="tag">&lt;<span class="name">div</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">title</span>&#125;&#125;</span><span class="xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span>&#x27;</span></span></span><br><span class="line">    &#125;);</span><br><span class="line"><span class="javascript">    Vue.component(<span class="string">&quot;todo-items&quot;</span>, &#123;</span></span><br><span class="line"><span class="javascript">        props: [<span class="string">&#x27;item&#x27;</span>],</span></span><br><span class="line"><span class="handlebars"><span class="xml">        template: &#x27;<span class="tag">&lt;<span class="name">li</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">item</span>&#125;&#125;</span><span class="xml"><span class="tag">&lt;<span class="name">button</span> @<span class="attr">click</span>=<span class="string">&quot;delete1&quot;</span>&gt;</span>删除<span class="tag">&lt;/<span class="name">button</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span>&#x27;,</span></span></span><br><span class="line">        methods: &#123;</span><br><span class="line"><span class="javascript">            delete1: <span class="function"><span class="keyword">function</span> (<span class="params">index</span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">                <span class="built_in">this</span>.$emit(<span class="string">&#x27;delete1&#x27;</span>, index)</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line"><span class="javascript">    <span class="keyword">var</span> vm = <span class="keyword">new</span> Vue(&#123;</span></span><br><span class="line"><span class="javascript">        el: <span class="string">&#x27;#vue&#x27;</span>,</span></span><br><span class="line">        data: &#123;</span><br><span class="line"><span class="javascript">            titleData: <span class="string">&#x27;人群&#x27;</span>,</span></span><br><span class="line"><span class="javascript">            itemsData: [<span class="string">&#x27;张三&#x27;</span>, <span class="string">&#x27;李四&#x27;</span>, <span class="string">&#x27;王五&#x27;</span>]</span></span><br><span class="line">        &#125;,</span><br><span class="line">        methods: &#123;</span><br><span class="line"><span class="javascript">            deleteItem: <span class="function"><span class="keyword">function</span> (<span class="params">index</span>) </span>&#123;</span></span><br><span class="line"><span class="javascript">                <span class="built_in">this</span>.itemsData.splice(index, <span class="number">1</span>);</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="新建vue-cli项目（手动安装）"><a href="#新建vue-cli项目（手动安装）" class="headerlink" title="新建vue-cli项目（手动安装）"></a>新建vue-cli项目（手动安装）</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">// 初始化项目，会新建一个myvue的文件夹，一路no</span><br><span class="line">vue init webpack myvue</span><br><span class="line"></span><br><span class="line">// 相当于安装依赖</span><br><span class="line"><span class="built_in">cd</span> myvue</span><br><span class="line">cnpm install</span><br><span class="line"></span><br><span class="line">// 启动项目</span><br><span class="line">npm run dev</span><br><span class="line"></span><br><span class="line">// 安装webpack（任何目录）</span><br><span class="line">cnpm install webpack -g</span><br><span class="line">// 安装webpack客户端（任何目录）</span><br><span class="line">cnpm install webpack-cli -g</span><br><span class="line"></span><br><span class="line">// 打包项目</span><br><span class="line">npm run build</span><br></pre></td></tr></table></figure>

<h2 id="webpack打包项目"><a href="#webpack打包项目" class="headerlink" title="webpack打包项目"></a>webpack打包项目</h2><p>新建一个空文件夹，目录结构如下</p>
<p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210313143329.png" alt="image-20210225164909212"></p>
<p>hello.js</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 暴露一个方法</span></span><br><span class="line"><span class="built_in">exports</span>.sayHi = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">document</span>.write(<span class="string">&quot;&lt;h1&gt;哈哈&lt;/h1&gt;&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>main.js，相当于程序主入口main函数</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> hello = <span class="built_in">require</span>(<span class="string">&quot;./hello&quot;</span>); <span class="comment">//类似于new一个对象，无需写后缀名</span></span><br><span class="line">hello.sayHi();</span><br></pre></td></tr></table></figure>

<p>webpack.config.js：打包的配置文件</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">    entry: <span class="string">&#x27;./modules/main.js&#x27;</span>,</span><br><span class="line">    output: &#123;</span><br><span class="line">        filename: <span class="string">&quot;./js/bundle.js&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>当前目录下执行==webpack==命令即可生成bundle.js文件，然后调用模块只需调用bundle.js</p>
<h2 id="路由"><a href="#路由" class="headerlink" title="路由"></a>路由</h2><p>默认项目内没有，需要安装</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">// 项目目录下</span><br><span class="line">cnpm install vue-router --save-dev</span><br></pre></td></tr></table></figure>

<p><strong>js相当于类，vue相当于html</strong></p>
<p>需要使用router的页面（相当于Controller），如index.js</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Vue <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">import</span> VueRouter <span class="keyword">from</span> <span class="string">&#x27;vue-router&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> Content <span class="keyword">from</span> <span class="string">&quot;../components/Content&quot;</span></span><br><span class="line"><span class="keyword">import</span> Main <span class="keyword">from</span> <span class="string">&#x27;../components/Main&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//安装路由</span></span><br><span class="line">Vue.use(VueRouter);</span><br><span class="line"></span><br><span class="line"><span class="comment">//配置导出路由</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">new</span> VueRouter(&#123;</span><br><span class="line">  routes: [</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="comment">//路由路径</span></span><br><span class="line">      path: <span class="string">&#x27;/content&#x27;</span>,</span><br><span class="line">      name: <span class="string">&#x27;content&#x27;</span>,</span><br><span class="line">      <span class="comment">//跳转路径，注意没有s！</span></span><br><span class="line">      component: Content</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="comment">//路由路径</span></span><br><span class="line">      path: <span class="string">&#x27;/main&#x27;</span>,</span><br><span class="line">      name: <span class="string">&#x27;main&#x27;</span>,</span><br><span class="line">      <span class="comment">//跳转路径</span></span><br><span class="line">      component: Main</span><br><span class="line">    &#125;</span><br><span class="line">  ]</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>main.js（程序主入口）调用</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Vue <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">import</span> App <span class="keyword">from</span> <span class="string">&#x27;./App&#x27;</span></span><br><span class="line"><span class="comment">//其中的“./”不能少！</span></span><br><span class="line"><span class="keyword">import</span> router <span class="keyword">from</span> <span class="string">&#x27;./router/index.js&#x27;</span></span><br><span class="line"></span><br><span class="line">Vue.config.productionTip = <span class="literal">false</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">new</span> Vue(&#123;</span><br><span class="line">  el: <span class="string">&#x27;#app&#x27;</span>,</span><br><span class="line">  <span class="comment">//配置路由</span></span><br><span class="line">  router,</span><br><span class="line">  components: &#123; App &#125;,</span><br><span class="line">  template: <span class="string">&#x27;&lt;App/&gt;&#x27;</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>App.vue（相当于index.html）</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div id&#x3D;&quot;app&quot;&gt;</span><br><span class="line">    &lt;!--使用路由跳转--&gt;</span><br><span class="line">    &lt;router-link to&#x3D;&quot;&#x2F;main&quot;&gt;跳到首页&lt;&#x2F;router-link&gt;</span><br><span class="line">    &lt;router-link to&#x3D;&quot;&#x2F;content&quot;&gt;跳到内容页&lt;&#x2F;router-link&gt;</span><br><span class="line">    &lt;router-view&gt;&lt;&#x2F;router-view&gt;</span><br><span class="line">  &lt;&#x2F;div&gt;</span><br><span class="line">&lt;&#x2F;template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">export default &#123;</span><br><span class="line">  name: &#39;App&#39;,</span><br><span class="line">&#125;</span><br><span class="line">&lt;&#x2F;script&gt;</span><br></pre></td></tr></table></figure>

<h3 id="路由传参"><a href="#路由传参" class="headerlink" title="路由传参"></a>路由传参</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">router-link</span> <span class="attr">:to</span>=<span class="string">&quot;&#123;name:&#x27;UserProfile&#x27;,params:&#123;id:1&#125;&#125;&quot;</span>&gt;</span>个人信息<span class="tag">&lt;/<span class="name">router-link</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="路由嵌套和404处理"><a href="#路由嵌套和404处理" class="headerlink" title="路由嵌套和404处理"></a>路由嵌套和404处理</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Vue <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">import</span> Router <span class="keyword">from</span> <span class="string">&#x27;vue-router&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> Main <span class="keyword">from</span> <span class="string">&#x27;../views/Main&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> Login <span class="keyword">from</span> <span class="string">&#x27;../views/Login&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> UserList <span class="keyword">from</span> <span class="string">&quot;../views/user/List&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> UserProfile <span class="keyword">from</span> <span class="string">&quot;../views/user/Profile&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> NotFound <span class="keyword">from</span> <span class="string">&quot;../views/NotFound&quot;</span>;</span><br><span class="line"></span><br><span class="line">Vue.use(Router);</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">new</span> Router(&#123;</span><br><span class="line">  <span class="comment">//路径不含#</span></span><br><span class="line">  mode: <span class="string">&#x27;history&#x27;</span>,</span><br><span class="line">  routes: [</span><br><span class="line">    &#123;</span><br><span class="line">      path: <span class="string">&#x27;/main/:name&#x27;</span>,</span><br><span class="line">      props: <span class="literal">true</span>,</span><br><span class="line">      component: Main,</span><br><span class="line">      children: [</span><br><span class="line">        &#123;<span class="attr">path</span>: <span class="string">&#x27;/user/list&#x27;</span>, <span class="attr">component</span>: UserList&#125;,</span><br><span class="line">        &#123;<span class="attr">path</span>: <span class="string">&#x27;/user/profile/:id&#x27;</span>, <span class="attr">name</span>: <span class="string">&#x27;UserProfile&#x27;</span>, <span class="attr">component</span>: UserProfile, <span class="attr">props</span>: <span class="literal">true</span>&#125;</span><br><span class="line">      ]</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      path: <span class="string">&#x27;/login&#x27;</span>,</span><br><span class="line">      component: Login,</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      path: <span class="string">&#x27;/goHome&#x27;</span>,</span><br><span class="line">      redirect: <span class="string">&#x27;/main/ &#x27;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      path: <span class="string">&#x27;*&#x27;</span>,</span><br><span class="line">      component: NotFound</span><br><span class="line">    &#125;</span><br><span class="line">  ]</span><br><span class="line">&#125;)</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>ProFile.vue</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;h1&gt;个人信息页&lt;&#x2F;h1&gt;</span><br><span class="line">    &lt;!--获取传值的两种方式--&gt;</span><br><span class="line">    &#123;&#123; $route.params.id &#125;&#125;</span><br><span class="line">    &#123;&#123; id &#125;&#125;</span><br><span class="line">  &lt;&#x2F;div&gt;</span><br><span class="line">&lt;&#x2F;template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">export default &#123;</span><br><span class="line">  props: [&#39;id&#39;],</span><br><span class="line">  name: &quot;UserProfile&quot;,</span><br><span class="line">  beforeRouteEnter: (to, from, next) &#x3D;&gt; &#123;</span><br><span class="line">    next(vm &#x3D;&gt; &#123;</span><br><span class="line">      vm.getData();</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;,</span><br><span class="line">  beforeRouteLeave: (to, from, next) &#x3D;&gt; &#123;</span><br><span class="line">  &#125;,</span><br><span class="line">  methods: &#123;</span><br><span class="line">    getData: function () &#123;</span><br><span class="line">      this.axios(&#123;</span><br><span class="line">        method:&quot;get&quot;,</span><br><span class="line">        url :&#39;http:&#x2F;&#x2F;localhost:8080&#x2F;static&#x2F;mock&#x2F;data.json&#39;</span><br><span class="line">      &#125;).then(function(response) &#123;</span><br><span class="line">          console.log(response)</span><br><span class="line">      &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;&#x2F;script&gt;</span><br></pre></td></tr></table></figure>

<h2 id="创建工程"><a href="#创建工程" class="headerlink" title="创建工程"></a>创建工程</h2><p>初始化项目–&gt;安装vue-router、element-ui–&gt;安装依赖</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">//element-ui</span><br><span class="line">npm i element-ui -S</span><br><span class="line"></span><br><span class="line">//sass加载器</span><br><span class="line">npm install sass-loader node-sass --save-dev</span><br><span class="line"></span><br><span class="line">//安装axios</span><br><span class="line">cnpm install --save axios vue-axios</span><br></pre></td></tr></table></figure>

<p>main.js</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Vue <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">import</span> App <span class="keyword">from</span> <span class="string">&#x27;./App&#x27;</span></span><br><span class="line"><span class="keyword">import</span> router <span class="keyword">from</span> <span class="string">&#x27;./router/index&#x27;</span></span><br><span class="line"><span class="keyword">import</span> ElementUI <span class="keyword">from</span> <span class="string">&#x27;element-ui&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">&#x27;element-ui/lib/theme-chalk/index.css&#x27;</span></span><br><span class="line"><span class="keyword">import</span> axios <span class="keyword">from</span> <span class="string">&#x27;axios&#x27;</span></span><br><span class="line"><span class="keyword">import</span> VueAxios <span class="keyword">from</span> <span class="string">&#x27;vue-axios&#x27;</span></span><br><span class="line"></span><br><span class="line">Vue.config.productionTip = <span class="literal">false</span></span><br><span class="line">Vue.use(router)</span><br><span class="line">Vue.use(ElementUI)</span><br><span class="line">Vue.use(VueAxios, axios)</span><br><span class="line"></span><br><span class="line"><span class="keyword">new</span> Vue(&#123;</span><br><span class="line">  el: <span class="string">&#x27;#app&#x27;</span>,</span><br><span class="line">  router,</span><br><span class="line">  render: <span class="function"><span class="params">h</span> =&gt;</span> h(App) <span class="comment">//ElementUI</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>目录结构</p>
<img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307223935.png" alt="image-20210225211921143" style="zoom:50%;" />

<h2 id="项目运行"><a href="#项目运行" class="headerlink" title="项目运行"></a>项目运行</h2><ul>
<li>cd projectName</li>
<li>cnpm install</li>
<li>npm run serve</li>
</ul>
<p>reactive响应式对象：const a = reactive({x:’y’})</p>
<p>ref存基本类型，存对象会转为换reactive处理：{xxx:yyy}，函数里用xxx.value</p>
<p>回调函数：const fun = ()=&gt;{}</p>
<h2 id="Ajax"><a href="#Ajax" class="headerlink" title="Ajax"></a>Ajax</h2><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">&lt;script type=<span class="string">&quot;text/javascript&quot;</span>&gt;</span><br><span class="line">    $(<span class="string">&quot;document&quot;</span>).ready(function()&#123;</span><br><span class="line">        $(<span class="string">&quot;#1&quot;</span>).click(function()&#123;</span><br><span class="line">            $.ajax(&#123;</span><br><span class="line">                url:<span class="string">&quot;http://localhost:8080/ajax/result.jsp&quot;</span>,</span><br><span class="line">                type:<span class="string">&quot;get&quot;</span>,</span><br><span class="line">                data:&#123;</span><br><span class="line">                    <span class="string">&quot;city&quot;</span>:document.getElementById(<span class="string">&quot;city&quot;</span>).value,</span><br><span class="line">                    <span class="string">&quot;street&quot;</span>:document.getElementById(<span class="string">&quot;street&quot;</span>).value</span><br><span class="line">                &#125;,</span><br><span class="line">                success:function (data,status) &#123;</span><br><span class="line">                    alert(status);</span><br><span class="line">                    $(<span class="string">&quot;#div1&quot;</span>).html(data);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;);</span><br><span class="line">&lt;/script&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">  城市：&lt;input id=<span class="string">&quot;city&quot;</span> type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;city&quot;</span>&gt;</span><br><span class="line">  街道：&lt;input id=<span class="string">&quot;street&quot;</span> type=<span class="string">&quot;text&quot;</span> name=<span class="string">&quot;street&quot;</span>&gt;</span><br><span class="line">  &lt;div id=<span class="string">&quot;div1&quot;</span>&gt;</span><br><span class="line">      服务器加载数据</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;button id=&quot;1&quot;&gt;通用测试&lt;/button&gt;</span><br><span class="line">&lt;/body&gt;</span><br></pre></td></tr></table></figure>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://yuzhenxin.gitee.io/2021/02/07/%E9%A2%98%E7%9B%AE/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="余振鑫">
      <meta itemprop="description" content="余振鑫的个人博客">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="余振鑫的Hexo博客">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/02/07/%E9%A2%98%E7%9B%AE/" class="post-title-link" itemprop="url">题目</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-02-07 00:00:00" itemprop="dateCreated datePublished" datetime="2021-02-07T00:00:00+08:00">2021-02-07</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-03-18 10:13:48" itemprop="dateModified" datetime="2021-03-18T10:13:48+08:00">2021-03-18</time>
              </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="题目"><a href="#题目" class="headerlink" title="题目"></a>题目</h1><h2 id="Java基础"><a href="#Java基础" class="headerlink" title="Java基础"></a>Java基础</h2><h3 id="获取二进制中1的个数"><a href="#获取二进制中1的个数" class="headerlink" title="获取二进制中1的个数"></a>获取二进制中1的个数</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">get1Num</span><span class="params">(Integer i)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> count = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">while</span> (i &gt; <span class="number">0</span>) &#123;</span><br><span class="line">        count += (i % <span class="number">2</span>);</span><br><span class="line">        i &gt;&gt;= <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> count;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="时间减法"><a href="#时间减法" class="headerlink" title="时间减法"></a>时间减法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> Integer <span class="title">getMinutes</span><span class="params">(Date date1, Date date2)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (date1 != <span class="keyword">null</span> &amp;&amp; date1 != <span class="keyword">null</span>) &#123;</span><br><span class="line">        Long time1 = date1.getTime();</span><br><span class="line">        Long time2 = date2.getTime();</span><br><span class="line">        Long minutes = Math.abs((time1 - time2) / (<span class="number">60</span> * <span class="number">1000</span>));</span><br><span class="line">        <span class="keyword">return</span> minutes.intValue();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="正则表达式去掉字符串中的数字"><a href="#正则表达式去掉字符串中的数字" class="headerlink" title="正则表达式去掉字符串中的数字"></a>正则表达式去掉字符串中的数字</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">filterQQ</span><span class="params">(String s)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> s.replaceAll(<span class="string">&quot;\\d&#123;0,10&#125;&quot;</span>,<span class="string">&quot;&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="类和实例初始化执行顺序"><a href="#类和实例初始化执行顺序" class="headerlink" title="类和实例初始化执行顺序"></a>类和实例初始化执行顺序</h3><ol>
<li><p>类初始化（即执行*&lt;clinit*&gt;()方法）：</p>
<ol>
<li>基类静态代码块，基类静态成员字段（并列优先级，按照代码中出现的先后顺序执行，且只有第一次加载时执行）</li>
<li>派生类静态代码块，派生类静态成员字段（并列优先级，按照代码中出现的先后顺序执行，且只有第一次加载时执行）</li>
</ol>
</li>
<li><p>实例初始化（即执行*&lt;init*&gt;()方法，第一行是super()）：</p>
<ol>
<li>基类普通代码块，基类普通成员字段（并列优点级，按代码中出现先后顺序执行）</li>
<li>基类构造函数</li>
<li>派生类普通代码块，派生类普通成员字段（并列优点级，按代码中出现先后顺序执行）</li>
<li>派生类构造函数</li>
</ol>
</li>
</ol>
<p><em>注意：非静态方法默认有对象this，表示正在创建的对象，因此父类执行子类重写的方法(静态方法不能被重写)</em></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Father</span></span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">int</span> j = method();</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">method</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.print(<span class="string">&quot;1&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">static</span>&#123;</span><br><span class="line">        System.out.print(<span class="string">&quot;2&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> i = test();</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">test</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.print(<span class="string">&quot;不会输出&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    &#123;</span><br><span class="line">        System.out.print(<span class="string">&quot;6&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    Father()&#123;</span><br><span class="line">        System.out.print(<span class="string">&quot;7&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Son</span> <span class="keyword">extends</span> <span class="title">Father</span></span>&#123;</span><br><span class="line">    <span class="keyword">static</span>&#123;</span><br><span class="line">        System.out.print(<span class="string">&quot;3&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">int</span> j = method();</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">method</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.print(<span class="string">&quot;4&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    &#123;</span><br><span class="line">        System.out.print(<span class="string">&quot;8&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> i = test();</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">test</span><span class="params">()</span></span>&#123;</span><br><span class="line">        System.out.print(<span class="string">&quot;5&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    Son()&#123;</span><br><span class="line">        System.out.print(<span class="string">&quot;9&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyTest</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>&#123;</span><br><span class="line">        Son s1 = <span class="keyword">new</span> Son(); <span class="comment">//1234567859</span></span><br><span class="line">        Son s2 = <span class="keyword">new</span> Son(); <span class="comment">//567859</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyTest</span> <span class="keyword">extends</span> <span class="title">B</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String name = <span class="string">&quot;MyTest&quot;</span>; <span class="comment">// 3</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">MyTest</span><span class="params">()</span> </span>&#123; <span class="comment">// 4</span></span><br><span class="line">        print();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">print</span><span class="params">()</span> </span>&#123; <span class="comment">// 2.1、5</span></span><br><span class="line">        System.out.println(name);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">new</span> MyTest(); <span class="comment">//输出null和MyTest：2.1时还没有执行3，name为null</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">B</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String name = <span class="string">&quot;B&quot;</span>; <span class="comment">// 1</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">B</span><span class="params">()</span> </span>&#123; <span class="comment">// 2</span></span><br><span class="line">        print();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">print</span><span class="params">()</span> </span>&#123; <span class="comment">// 不会调用</span></span><br><span class="line">        System.out.println(name);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="方法传递参数"><a href="#方法传递参数" class="headerlink" title="方法传递参数"></a>方法传递参数</h3><ul>
<li>形参是基本数据类型，传递数值</li>
<li>实参是引用类型，传递地址值（String、包装类不可变，拼接产生新的对象）<br><img src="https://i.imgur.com/29ns0YZ.png"></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">A</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>&#123;</span><br><span class="line">        <span class="keyword">int</span> i = <span class="number">1</span>;</span><br><span class="line">        String s = <span class="string">&quot;hello&quot;</span>;</span><br><span class="line">        Integer num = <span class="number">200</span>;</span><br><span class="line">        <span class="keyword">int</span>[] arr = &#123;<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>&#125;;</span><br><span class="line">        MyData m = <span class="keyword">new</span> MyData();</span><br><span class="line">        change(i, s, num, arr, m); <span class="comment">//i,s,num不变</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="title">change</span><span class="params">(<span class="keyword">int</span> j, String s, Integer n, <span class="keyword">int</span>[] a, MyData a)</span></span>&#123;</span><br><span class="line">        j += <span class="number">1</span>;</span><br><span class="line">        s += <span class="string">&quot;world&quot;</span>;</span><br><span class="line">        n += <span class="number">1</span>;</span><br><span class="line">        a[<span class="number">0</span>] += <span class="number">1</span>;</span><br><span class="line">        m.a += <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyData</span></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> a = <span class="number">10</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="方法参数传值问题"><a href="#方法参数传值问题" class="headerlink" title="方法参数传值问题"></a>方法参数传值问题</h3><p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210316101937.png" alt="image-20210316101930325"></p>
<h3 id="一个n级台阶一次只能走1级或2级，问有几种走法"><a href="#一个n级台阶一次只能走1级或2级，问有几种走法" class="headerlink" title="一个n级台阶一次只能走1级或2级，问有几种走法"></a>一个n级台阶一次只能走1级或2级，问有几种走法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//递归</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">f</span><span class="params">(<span class="keyword">int</span> n)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(n&lt;<span class="number">1</span>)&#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(n + <span class="string">&quot;不能小于1&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(n==<span class="number">1</span> || n==<span class="number">2</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> n;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> f(n-<span class="number">1</span>) + f(n-<span class="number">2</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//循环</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">loop</span><span class="params">(<span class="keyword">int</span> n)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(n&lt;<span class="number">1</span>)&#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> IllegalArgumentException(n + <span class="string">&quot;不能小于1&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(n==<span class="number">1</span> || n==<span class="number">2</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> n;</span><br><span class="line">    &#125;    </span><br><span class="line">    <span class="keyword">int</span> one = <span class="number">2</span>; <span class="comment">//最后剩一级的走法，初始化为2</span></span><br><span class="line">    <span class="keyword">int</span> two = <span class="number">1</span>; <span class="comment">//最后剩两级的走法，初始化为1</span></span><br><span class="line">    <span class="keyword">int</span> sum = <span class="number">0</span>; <span class="comment">//总走法</span></span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">3</span>; i &lt; n; i++)&#123;</span><br><span class="line">        two = one;</span><br><span class="line">        one = sum;</span><br><span class="line">        sum = two + one;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> sum;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="成员变量（全局变量）与局部变量"><a href="#成员变量（全局变量）与局部变量" class="headerlink" title="成员变量（全局变量）与局部变量"></a>成员变量（全局变量）与局部变量</h3><ul>
<li>堆存放实例对象（类名），一个实例对象内部存放实例变量（成员变量i、j有默认值0），每个对象在堆中有不同的空间</li>
<li>栈存放局部变量，方法结束自动释放（方法为单位，方法里存放局部变量）。先是开辟main()方法，创建对象时调用*&lt;init*&gt;()方法，开辟新空间</li>
<li>方法区存放类信息、常量、类变量。开辟A.class空间存放类变量（成员变量s默认值0）<br><img src="https://i.imgur.com/6Je7TaN.png">    </li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">A</span></span>&#123;</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">int</span> s;</span><br><span class="line">    <span class="keyword">int</span> i;</span><br><span class="line">    <span class="keyword">int</span> j;</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">int</span> i = <span class="number">1</span>; <span class="comment">//局部变量，只在创建对象时执行一次</span></span><br><span class="line">        i++; <span class="comment">//就近原则，修改上一行的i，其实这两行都没用</span></span><br><span class="line">        j++;</span><br><span class="line">        s++;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test</span><span class="params">(<span class="keyword">int</span> j)</span></span>&#123;</span><br><span class="line">        j++;</span><br><span class="line">        i++; <span class="comment">//成员变量的i</span></span><br><span class="line">        s++;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>&#123;</span><br><span class="line">        A a1 = <span class="keyword">new</span> A();</span><br><span class="line">        A a2 = <span class="keyword">new</span> A();</span><br><span class="line">        a1.test(<span class="number">10</span>);</span><br><span class="line">        a1.test(<span class="number">20</span>);</span><br><span class="line">        a2.test(<span class="number">30</span>);</span><br><span class="line">        System.out.println(a1.i + <span class="string">&quot;,&quot;</span> + a1.j + <span class="string">&quot;,&quot;</span> + a1.s); <span class="comment">//2,1,5</span></span><br><span class="line">        System.out.println(a2.i + <span class="string">&quot;,&quot;</span> + a2.j + <span class="string">&quot;,&quot;</span> + a2.s); <span class="comment">//1,1,5</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="amp-符号"><a href="#amp-符号" class="headerlink" title="~&amp;|^符号"></a>~&amp;|^符号</h3><p><del>取反，-n = \</del>n + 1，故~n = -n - 1</p>
<p>&amp;按位与（乘法）</p>
<p>|按位或</p>
<p>^异或（加法）</p>
<h2 id="项目技术栈"><a href="#项目技术栈" class="headerlink" title="项目技术栈"></a>项目技术栈</h2><ol start="3">
<li><p>单点登录<br>多用于分布式系统</p>
<pre><code>1. WEB应用检查cookie是否有token
2. 否则重定向到认证中心登录
3. 再带着token跳转WEB应用，将token写入cookie
4. 用户继续访问，检查cookie存在token，认证身份
</code></pre>
</li>
<li><p>购物车实现</p>
<ul>
<li>未登录存放数据：<ul>
<li>Redis</li>
<li>Cookie</li>
</ul>
</li>
<li>已登录存放数据：<ul>
<li>Redis：<ul>
<li>Hash：hset(key,field,value)</li>
</ul>
</li>
<li>数据库（Oracle、Mysql）</li>
</ul>
</li>
<li>未登录展示：<ul>
<li>从cookie获取数据</li>
</ul>
</li>
<li>登录展示：<ul>
<li>Redis+cookie</li>
</ul>
</li>
</ul>
</li>
<li><p>消息队列<br>背景：在分布式系统处理高并发（请求过多来不及处理导致阻塞）<br>解决：消息队列（异步通信）</p>
<ul>
<li>异步：写数据库同时发送一个消息队列，不管后续结果</li>
<li>并行：写数据库同时发送多个消息队列，不管后续结果</li>
<li>排队</li>
</ul>
</li>
</ol>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://yuzhenxin.gitee.io/2021/01/20/Linux/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="余振鑫">
      <meta itemprop="description" content="余振鑫的个人博客">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="余振鑫的Hexo博客">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/01/20/Linux/" class="post-title-link" itemprop="url">Linux</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-01-20 00:00:00" itemprop="dateCreated datePublished" datetime="2021-01-20T00:00:00+08:00">2021-01-20</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2022-01-20 19:55:05" itemprop="dateModified" datetime="2022-01-20T19:55:05+08:00">2022-01-20</time>
              </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="Linux"><a href="#Linux" class="headerlink" title="Linux"></a>Linux</h1><h2 id="Linux常见命令"><a href="#Linux常见命令" class="headerlink" title="Linux常见命令"></a>Linux常见命令</h2><ul>
<li>pwd：显示当前所在目录路径</li>
<li>ls和ll：列出当前目录所有文件，后者更详细</li>
<li>touch xx：新建文件xx</li>
<li>rm xx：删除文件xx</li>
<li>mkdir：新建目录</li>
<li>rm -r xx：删除文件夹xx</li>
<li>mv 文件名 文件夹名</li>
<li>clear和reset</li>
<li>history</li>
</ul>
<h3 id="rpm安装与卸载"><a href="#rpm安装与卸载" class="headerlink" title="rpm安装与卸载"></a>rpm安装与卸载</h3><ul>
<li>rpm -ivh –nodeps XXX.rpm</li>
<li>rpm -qa|grep XXX</li>
<li>rpm -e –nodeps 软件包（上面的结果）</li>
</ul>
<h3 id="开放端口"><a href="#开放端口" class="headerlink" title="开放端口"></a>开放端口</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## 查看防火墙状态</span></span><br><span class="line">systemctl status firewalld</span><br><span class="line"><span class="comment">## 开启端口</span></span><br><span class="line">firewall-cmd --zone=public --add-port=8080/tcp --permanent</span><br><span class="line"><span class="comment">## 重启防火墙</span></span><br><span class="line">firewall-cmd --reload</span><br><span class="line"><span class="comment">## 查询开放端口</span></span><br><span class="line">firewall-cmd --list-port</span><br><span class="line"><span class="comment">## 重启docker</span></span><br><span class="line">systemctl restart docker</span><br><span class="line"></span><br><span class="line"><span class="comment">## 启动docker（Ubuntu）</span></span><br><span class="line">sudo service docker start</span><br></pre></td></tr></table></figure>

<p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210318102251.png" alt="image-20210316165836806"></p>
<h3 id="Centos配置Java环境变量"><a href="#Centos配置Java环境变量" class="headerlink" title="Centos配置Java环境变量"></a>Centos配置Java环境变量</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vim /etc/profile</span><br></pre></td></tr></table></figure>

<p>添加：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">JAVA_HOME&#x3D;&#x2F;usr&#x2F;java&#x2F;jdk1.8.0_281</span><br><span class="line">PATH&#x3D;$PATH:$JAVA_HOME&#x2F;bin</span><br><span class="line">CLASSPATH&#x3D;.:$JAVA_HOME&#x2F;lib</span><br><span class="line">export JAVA_HOME PATH CLASSPATH</span><br><span class="line"></span><br><span class="line">JAVA_HOME&#x3D;&#x2F;usr&#x2F;java&#x2F;jdk-11.0.7</span><br><span class="line">PATH&#x3D;$PATH:$JAVA_HOME&#x2F;bin</span><br><span class="line">export PATH JAVA_HOME</span><br></pre></td></tr></table></figure>

<h2 id="Git"><a href="#Git" class="headerlink" title="Git"></a>Git</h2><p><strong>分布式版本控制</strong>，对比SVN集中版本控制：</p>
<ul>
<li>SVN所有版本数据保存在服务器，开发者从服务器上同步</li>
<li>Git中每个人都有仓库全部信息，防止服务器损坏导致数据丢失。</li>
</ul>
<h3 id="常见命令"><a href="#常见命令" class="headerlink" title="常见命令"></a>常见命令</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#查看配置文件</span></span><br><span class="line">git config -l</span><br><span class="line"></span><br><span class="line"><span class="comment">#配置用户属性</span></span><br><span class="line">git config --global user.name <span class="string">&quot;yuzhenxin&quot;</span></span><br><span class="line">git config --global user.email <span class="string">&quot;1399079216@qq.com&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#查看系统配置</span></span><br><span class="line">git config --system --list</span><br><span class="line"></span><br><span class="line"><span class="comment">#查看当前用户配置</span></span><br><span class="line">git config --global --list</span><br><span class="line"></span><br><span class="line">// <span class="built_in">local</span>仓库级别 -&gt; global用户级别 -&gt; system系统级别</span><br><span class="line">git config --<span class="built_in">local</span> paper.branch <span class="literal">false</span></span><br><span class="line"></span><br><span class="line">// 注意等号前后不能有空格</span><br><span class="line">git branch --set-upstream-to=origin/coding-yzx</span><br><span class="line"></span><br><span class="line">// 分支改名</span><br><span class="line">git branch -m a b</span><br><span class="line"></span><br><span class="line">// 使.gitignore生效</span><br><span class="line">git rm -r --cached .</span><br><span class="line">git add .</span><br><span class="line">git commit -m <span class="string">&quot;.gitignore now work&quot;</span></span><br></pre></td></tr></table></figure>

<p>系统配置文件路径：D:\Programming\Git\etc\gitconfig</p>
<p>用户配置文件路径：‪C:\Users\YuZhenXin.gitconfig</p>
<h3 id="基本理论"><a href="#基本理论" class="headerlink" title="基本理论"></a>基本理论</h3><p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210318102155.png" alt="image-20210306215824413"></p>
<p><strong>创建仓库：</strong></p>
<ul>
<li>git init</li>
<li>git clone [url]</li>
</ul>
<p>Working Directory工作区：存放代码的地方</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git add .</span><br></pre></td></tr></table></figure>

<p>Stage暂存区：保存即将提交的文件列表信息</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git commit -m <span class="string">&quot;修改信息&quot;</span></span><br></pre></td></tr></table></figure>

<p>Repository本地仓库</p>
<p>Remote远程仓库</p>
<p><strong>忽略文件提交</strong>：主目录下.gitignore</p>
<h3 id="配置远程仓库"><a href="#配置远程仓库" class="headerlink" title="配置远程仓库"></a>配置远程仓库</h3><ul>
<li><p>在C:\Users\YuZhenXin\.ssh下运行</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh-keygen -t rsa</span><br></pre></td></tr></table></figure></li>
<li><p>‪将C:\Users\YuZhenXin\.ssh\id_rsa.pub内容粘贴到Gitee生成SSH公钥</p>
</li>
<li><p>创建仓库</p>
</li>
<li><p>git clone [url]（注意选择ssh链接！）</p>
</li>
</ul>
<h3 id="分支"><a href="#分支" class="headerlink" title="分支"></a>分支</h3><p><strong>分支相当于一棵树（图），根节点为最初版本，不同路径代表不同分支。通过git checkout选择不同分支进行操作，最终希望不同分支会合master</strong></p>
<p>git merge xx表示指向xx（xx为父节点）</p>
<p>git xx rebase yy会将xx分支拉到yy下面（xx指向yy）</p>
<p>git checkout可以指向结点</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#查看分支</span></span><br><span class="line">git branch</span><br><span class="line"><span class="comment">#查看远程分支</span></span><br><span class="line">git branch -r</span><br><span class="line"></span><br><span class="line"><span class="comment">#新建分支(仍在原分支)</span></span><br><span class="line">git branch xx</span><br><span class="line"><span class="comment">#切换分支</span></span><br><span class="line">git checkout xx</span><br><span class="line"><span class="comment">#创建分支并跳转到该分支</span></span><br><span class="line">git checkout -b xx</span><br><span class="line"></span><br><span class="line"><span class="comment">#合并ab分支：在a分支下</span></span><br><span class="line">git merge b</span><br><span class="line"></span><br><span class="line"><span class="comment">#删除分支</span></span><br><span class="line">git branch -d xx</span><br><span class="line"><span class="comment">#删除远程分支</span></span><br><span class="line">git branch -dr xx</span><br></pre></td></tr></table></figure>

<h2 id="Hexo博客"><a href="#Hexo博客" class="headerlink" title="Hexo博客"></a>Hexo博客</h2><h3 id="准备（与当前目录无关）"><a href="#准备（与当前目录无关）" class="headerlink" title="准备（与当前目录无关）"></a>准备（与当前目录无关）</h3><p>npm install –registry=<a target="_blank" rel="noopener" href="https://registry.npm.taobao.org/">https://registry.npm.taobao.org</a></p>
<p>npm install -g cnpm –registry=<a target="_blank" rel="noopener" href="https://registry.npm.taobao.org/">https://registry.npm.taobao.org</a></p>
<p>cnpm install -g hexo-cli</p>
<h3 id="本地部署"><a href="#本地部署" class="headerlink" title="本地部署"></a>本地部署</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#在博客目录下</span></span><br><span class="line">hexo init</span><br><span class="line"></span><br><span class="line"><span class="comment">#新建文件hello</span></span><br><span class="line">hexo n <span class="string">&quot;hello&quot;</span></span><br><span class="line"><span class="comment">#清除h</span></span><br><span class="line">hexo clean</span><br><span class="line"><span class="comment">#编译生成静态页面</span></span><br><span class="line">hexo g</span><br><span class="line"><span class="comment">#启动，预览localhost:4000</span></span><br><span class="line">hexo s</span><br><span class="line"></span><br><span class="line"><span class="comment">#远程部署</span></span><br><span class="line">cnpm install hexo-deployer-git --save</span><br><span class="line">修改_config.yml:</span><br><span class="line">	<span class="comment">#Deployment</span></span><br><span class="line">	deploy</span><br><span class="line">		<span class="built_in">type</span>: git</span><br><span class="line">		repo: git@gitee.com:yuzhenxin/yuzhenxin.git</span><br><span class="line">		branch: master</span><br><span class="line">hexo d</span><br><span class="line">	</span><br><span class="line"><span class="comment">#修改主题</span></span><br><span class="line">git <span class="built_in">clone</span> URL</span><br><span class="line">修改_config.yml:</span><br><span class="line">	theme: xxx</span><br><span class="line">hexo clean</span><br><span class="line">hexo g</span><br><span class="line">hexo d</span><br></pre></td></tr></table></figure>

<p>配置next主题具体参考</p>
<p><a target="_blank" rel="noopener" href="https://www.jianshu.com/p/7951e239ae04">https://www.jianshu.com/p/7951e239ae04</a></p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/nightmare_dimple/article/details/86661502">https://blog.csdn.net/nightmare_dimple/article/details/86661502</a></p>
<h2 id="Docker"><a href="#Docker" class="headerlink" title="Docker"></a>Docker</h2><p>容器和镜像就类比实例对象和类</p>
<ul>
<li><p>获取镜像（安装包）：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker pull redis</span><br></pre></td></tr></table></figure></li>
<li><p>查看镜像：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">docker images</span><br><span class="line">mkdir -p /usr/<span class="built_in">local</span>/docker/redis</span><br><span class="line">mkdir -p /usr/<span class="built_in">local</span>/docker/mysql</span><br></pre></td></tr></table></figure></li>
<li><p>创建redis容器：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -p 6379:6379 --name redis -v /usr/<span class="built_in">local</span>/docker/redis/redis.conf:/etc/redis/redis.conf -v /usr/<span class="built_in">local</span>/docker/redis/data:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes</span><br></pre></td></tr></table></figure>

<p>以配置文件启动redis，加载容器内的conf文件，最终找到的是挂载的目录/usr/local/docker/redis/redis.conf</p>
</li>
<li><p>创建mysql容器：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -p 3306:3306 --name mysql -v /usr/<span class="built_in">local</span>/docker/mysql/conf:/etc/mysql/conf.d -v /usr/<span class="built_in">local</span>/docker/mysql/logs:/logs -v /usr/<span class="built_in">local</span>/docker/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=yuzhenxin2758 -d -i mysql</span><br></pre></td></tr></table></figure>

<p>简化版：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -d -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=yuzhenxin2758 mysql</span><br></pre></td></tr></table></figure></li>
<li><p>创建rabbitmq容器：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 -v /usr/<span class="built_in">local</span>/docker/rabbitmq/data:/var/lib/rabbitmq -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=yuzhenxin2758 rabbitmq:3.8.8-management</span><br></pre></td></tr></table></figure></li>
<li><p>安装Nginx</p>
<figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">docker pull nginx:latest  <span class="comment">#拉取官方的最新版本的镜像</span></span><br><span class="line"></span><br><span class="line">docker images  <span class="comment">#查看是否已安装了 nginx</span></span><br><span class="line"></span><br><span class="line">docker <span class="keyword">run</span><span class="bash"> -d -p 8080:80 --name nginx -v /usr/<span class="built_in">local</span>/docker/nginx/conf/nginx.conf:/etc/nginx/conf/nginx.conf -v /usr/<span class="built_in">local</span>/docker/nginx/logs:/var/<span class="built_in">log</span>/nginx nginx</span></span><br><span class="line">docker <span class="keyword">run</span><span class="bash"> --name nginx -p 80:80 -d nginx  <span class="comment">#运行 nginx 容器</span></span></span><br><span class="line"></span><br><span class="line">docker exec -it <span class="number">299</span>b6d99cc1c bash  <span class="comment">#进入Nginx容器中</span></span><br><span class="line"><span class="comment"># 日志位置：/var/log/nginx/</span></span><br><span class="line"><span class="comment"># 配置文件位置：/etc/nginx/</span></span><br><span class="line"><span class="comment"># 项目位置：/usr/share/nginx/html</span></span><br></pre></td></tr></table></figure></li>
<li><p>查看容器：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker ps -a</span><br></pre></td></tr></table></figure></li>
<li><p>启动XXX容器</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker start XXX</span><br></pre></td></tr></table></figure></li>
<li><p>进入XXX容器：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker <span class="built_in">exec</span> -it XXX /bin/bash</span><br></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## redis</span></span><br><span class="line">redis-cli</span><br><span class="line"></span><br><span class="line"><span class="comment">## mysql</span></span><br><span class="line">mysql -uroot -p</span><br><span class="line"></span><br><span class="line"><span class="comment">##退出容器</span></span><br><span class="line"><span class="built_in">exit</span></span><br></pre></td></tr></table></figure></li>
<li><p>关闭XXX容器：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker stop XXX</span><br></pre></td></tr></table></figure></li>
<li><p>移除XXX容器：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker rm XXX</span><br></pre></td></tr></table></figure></li>
<li><p>自启：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## 设置XXX、YYY自启</span></span><br><span class="line">docker update --restart=always XXX YYY</span><br><span class="line"><span class="comment">## 设置mysql开机自动启动</span></span><br><span class="line">docker update mysql --restart=always</span><br></pre></td></tr></table></figure></li>
</ul>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://yuzhenxin.gitee.io/2021/01/11/Java%E6%A1%86%E6%9E%B6/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="余振鑫">
      <meta itemprop="description" content="余振鑫的个人博客">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="余振鑫的Hexo博客">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2021/01/11/Java%E6%A1%86%E6%9E%B6/" class="post-title-link" itemprop="url">Java框架</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2021-01-11 00:00:00" itemprop="dateCreated datePublished" datetime="2021-01-11T00:00:00+08:00">2021-01-11</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2022-01-20 20:06:58" itemprop="dateModified" datetime="2022-01-20T20:06:58+08:00">2022-01-20</time>
              </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="Java框架"><a href="#Java框架" class="headerlink" title="Java框架"></a>Java框架</h1><h2 id="Spring"><a href="#Spring" class="headerlink" title="Spring"></a>Spring</h2><h3 id="IOC"><a href="#IOC" class="headerlink" title="IOC"></a>IOC</h3><h4 id="一种实现方式"><a href="#一种实现方式" class="headerlink" title="一种实现方式"></a>一种实现方式</h4><ol>
<li>配置包扫描路径</li>
<li>递归包扫描.class文件</li>
<li>反射确定需要交给IOC管理的类</li>
<li>对需要注入的类进行依赖注入</li>
</ol>
<h4 id="AOP"><a href="#AOP" class="headerlink" title="AOP"></a>AOP</h4><p>OOP的补充，OOP在引入公共行为和交叉逻辑时，会写大量重复的代码，如日志、异常等。AOP可以将这些功能封装成一个切面，注入到对象中</p>
<h3 id="Bean作用域"><a href="#Bean作用域" class="headerlink" title="Bean作用域"></a>Bean作用域</h3><p>scope指定：</p>
<ul>
<li>singleton（默认），IOC一创建就创建单例bean对象，每次得到都是同一个</li>
<li>prototype，调用getBean()方法才实例化bean，每次得到不同的对象</li>
<li>request（Web环境），每次请求实例化一个新的bean</li>
<li>session（Web环境），一次会话共享一个bean</li>
</ul>
<h3 id="事务"><a href="#事务" class="headerlink" title="事务"></a>事务</h3><p>事务是程序中一系列严密的操作，所有操作执行必须成功完成，否则在每个操作所做的更改将会被撤销，这也是事务的原子性（要么成功，要么失败）</p>
<h4 id="特性"><a href="#特性" class="headerlink" title="特性"></a>特性</h4><ul>
<li>原子性：事务是数据库逻辑工作单元，事务中包含的操作<strong>要么都执行成功，要么都执行失败</strong></li>
<li>一致性：事务执行的结果必须是使数据库数据<strong>从一个一致性状态变到另外一种一致性状态</strong>。当事务执行成功后就说数据库处于一致性状态。如果在执行过程中发生错误，这些未完成事务对数据库所做的修改有一部分已写入物理数据库，这时数据库就处于不一致状态</li>
<li>隔离性：一个事务的执行过程中不能影响到其他事务的执行，即一个事务内部的操作及使用的数据对其他事务是隔离的，并发执行各个事务之间<strong>互不干扰</strong></li>
<li>持续性：一个事务执一旦提交，它对数据库数据的改变是<strong>永久性</strong>的。之后的其它操作不应该对其执行结果有任何影响</li>
</ul>
<h4 id="隔离级别"><a href="#隔离级别" class="headerlink" title="隔离级别"></a>隔离级别</h4><ul>
<li>read uncommited（读未提交）：是最低的事务隔离级别，它允许另外一个事务可以看到这个事务未提交的数据</li>
<li>read commited（读已提交）：保证一个事务提交后才能被另外一个事务读取。另外一个事务不能读取该事物未提交的数据</li>
<li>repeatable read（可重复读）：这种事务隔离级别可以防止脏读，不可重复读。但是可能会出现幻读。</li>
<li>serializable（序列化）：这是花费最高代价但最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读，不可重复读之外，还避免了幻读。</li>
</ul>
<h4 id="传播特性"><a href="#传播特性" class="headerlink" title="传播特性"></a>传播特性</h4><ul>
<li><strong>propagation_requierd（默认）</strong>：如果当前没有事务，就<strong>新建</strong>一个事务，如果已存在一个事务中，<strong>加入</strong>到这个事务中，最常见的选择</li>
<li>propagation_supports：<strong>支持</strong>当前事务，如果没有当前事务，就以<strong>非事务方法</strong>执行</li>
<li>propagation_mandatory：使用当前事务，如果没有当前事务，就抛出<strong>异常</strong></li>
<li>propagation_required_new：<strong>新建事务</strong>，如果当前存在事务，把当前事务挂起</li>
<li>propagation_not_supported：以<strong>非事务方式</strong>执行操作，如果当前存在事务，就把当前事务<strong>挂起</strong></li>
<li>propagation_never：以<strong>非事务方式</strong>执行操作，如果当前事务存在则抛出<strong>异常</strong></li>
<li>propagation_nested：如果当前存在事务，则在<strong>嵌套事务内</strong>执行。如果当前没有事务，就新建一个事务</li>
</ul>
<h2 id="Spring-MVC"><a href="#Spring-MVC" class="headerlink" title="Spring MVC"></a>Spring MVC</h2><p>SpringMVC中POST和GET请求中文乱码<br>POST:</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">filter</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">filter-name</span>&gt;</span>CharacterEncodingFilter<span class="tag">&lt;/<span class="name">filter-name</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">filter-class</span>&gt;</span>org.springframework.web.filter.CharacterEncodingFilter<span class="tag">&lt;/<span class="name">filter-class</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">init-param</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">param-name</span>&gt;</span>encoding<span class="tag">&lt;/<span class="name">param-name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">param-value</span>&gt;</span>UTF-8<span class="tag">&lt;/<span class="name">param-value</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">init-param</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 响应字符集 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">init-param</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">param-name</span>&gt;</span>forceEncoding<span class="tag">&lt;/<span class="name">param-name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">param-value</span>&gt;</span>true<span class="tag">&lt;/<span class="name">param-value</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">init-param</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">filter</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">filter-mapping</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">filter-name</span>&gt;</span>CharacterEncodingFilter<span class="tag">&lt;/<span class="name">filter-name</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">url-pattern</span>&gt;</span>/*<span class="tag">&lt;/<span class="name">url-pattern</span>&gt;</span></span><br><span class="line">&lt;/filter-mapping</span><br></pre></td></tr></table></figure>

<p>GET:<br>修改Servers的server.xml的第一个Connector标签增加属性URIEncoding=”UTF-8”</p>
<p>SpringMVC工作流程</p>
<p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307223755.png" alt="image-20210223222301329"></p>
<h2 id="Spring-Boot"><a href="#Spring-Boot" class="headerlink" title="Spring Boot"></a>Spring Boot</h2><h3 id="拦截器"><a href="#拦截器" class="headerlink" title="拦截器"></a>拦截器</h3><p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307223810.png" alt="20210307143413"></p>
<ol>
<li><p>首先实现HandlerInterceptor接口</p>
<p>preHandle() –&gt; 目标方法 –&gt; postHandle() –&gt; 页面渲染 –&gt; afterCompletion()</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LoginInterceptor</span> <span class="keyword">implements</span> <span class="title">HandlerInterceptor</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">preHandle</span><span class="params">(HttpServletRequest request, HttpServletResponse response, Object handler)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        HttpSession session = request.getSession();</span><br><span class="line"></span><br><span class="line">        Object loginUser = session.getAttribute(<span class="string">&quot;loginUser&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (loginUser != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="comment">// 放行</span></span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 拦截</span></span><br><span class="line">        request.setAttribute(<span class="string">&quot;msg&quot;</span>, <span class="string">&quot;请先登录！&quot;</span>);</span><br><span class="line">        request.getRequestDispatcher(<span class="string">&quot;/&quot;</span>).forward(request, response);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">postHandle</span><span class="params">(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">afterCompletion</span><span class="params">(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li><p>配置拦截器</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">WebConfig</span> <span class="keyword">implements</span> <span class="title">WebMvcConfigurer</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">addInterceptors</span><span class="params">(InterceptorRegistry registry)</span> </span>&#123;</span><br><span class="line">        registry.addInterceptor(<span class="keyword">new</span> LoginInterceptor())</span><br><span class="line">                .addPathPatterns(<span class="string">&quot;/**&quot;</span>)</span><br><span class="line">                .excludePathPatterns(<span class="string">&quot;/&quot;</span>, <span class="string">&quot;/login&quot;</span>,<span class="string">&quot;/favicon.ico&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ol>
<h3 id="文件上传"><a href="#文件上传" class="headerlink" title="文件上传"></a>文件上传</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">th:action</span>=<span class="string">&quot;@&#123;/upload&#125;&quot;</span> <span class="attr">method</span>=<span class="string">&quot;post&quot;</span> <span class="attr">enctype</span>=<span class="string">&quot;multipart/form-data&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">label</span>&gt;</span>头像<span class="tag">&lt;/<span class="name">label</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;file&quot;</span> <span class="attr">name</span>=<span class="string">&quot;headerImg&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">label</span>&gt;</span>其他照片<span class="tag">&lt;/<span class="name">label</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;file&quot;</span> <span class="attr">name</span>=<span class="string">&quot;photos&quot;</span> <span class="attr">multiple</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">button</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span>&gt;</span>提交<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@PostMapping(&quot;/upload&quot;)</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">upload</span><span class="params">(<span class="meta">@RequestPart(&quot;headerImg&quot;)</span> MultipartFile headerImg,</span></span></span><br><span class="line"><span class="function"><span class="params">                     <span class="meta">@RequestPart(&quot;photos&quot;)</span> MultipartFile[] photos)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (!headerImg.isEmpty()) &#123;</span><br><span class="line">        String filename = headerImg.getOriginalFilename();</span><br><span class="line">        headerImg.transferTo(<span class="keyword">new</span> File(<span class="string">&quot;C:\\Users\\YuZhenXin\\Desktop\\draft\\springboot\\cache\\&quot;</span> + filename));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (photos.length &gt; <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">for</span> (MultipartFile photo : photos) &#123;</span><br><span class="line">            <span class="keyword">if</span> (!photo.isEmpty()) &#123;</span><br><span class="line">                String filename = photo.getOriginalFilename();</span><br><span class="line">                photo.transferTo(<span class="keyword">new</span> File(<span class="string">&quot;C:\\Users\\YuZhenXin\\Desktop\\draft\\springboot\\cache\\&quot;</span> + filename));</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;main&quot;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>注意配置文件大小</strong></p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">servlet:</span></span><br><span class="line">    <span class="attr">multipart:</span></span><br><span class="line">      <span class="attr">max-file-size:</span> <span class="string">10MB</span></span><br><span class="line">      <span class="attr">max-request-size:</span> <span class="string">100MB</span></span><br></pre></td></tr></table></figure>

<h3 id="定制化"><a href="#定制化" class="headerlink" title="定制化"></a>定制化</h3><h4 id="方式"><a href="#方式" class="headerlink" title="方式"></a>方式</h4><ul>
<li>修改配置文件</li>
<li>xxxxxCustomizer</li>
<li>编写自定义的配置类  xxxConfiguration + @Bean替换、增加容器中默认组件；视图解析器 </li>
<li><strong>Web应用：编写一个配置类实现 WebMvcConfigurer 接口 + @Bean给容器中再扩展一些组件</strong></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyWebConfig</span> <span class="keyword">implements</span> <span class="title">WebMvcConfigurer</span></span></span><br></pre></td></tr></table></figure>

<ul>
<li>@EnableWebMvc + WebMvcConfigurer —— @Bean  可以<strong>全面接管SpringMVC</strong>，所有规则全部自己重新配置； 实现定制和扩展功能<ul>
<li>原理<ul>
<li>1、WebMvcAutoConfiguration  默认的SpringMVC的自动配置功能类。静态资源、欢迎页…..</li>
<li>2、一旦使用 @<strong>EnableWebMvc</strong> 会 @Import(<strong>DelegatingWebMvcConfiguration.class</strong>)</li>
<li>3、DelegatingWebMvcConfiguration 的作用，只保证SpringMVC最基本的使用<ul>
<li>把所有系统中的 WebMvcConfigurer 拿过来。所有功能的定制都是这些 WebMvcConfigurer  合起来一起生效</li>
<li>自动配置了一些非常底层的组件：RequestMappingHandlerMapping等，这些组件依赖的组件都是从容器中获取</li>
<li>public class <strong>DelegatingWebMvcConfiguration</strong> extends <strong>WebMvcConfigurationSupport</strong></li>
</ul>
</li>
<li>4、<strong>WebMvcAutoConfiguration</strong> 里面的配置要能生效必须@ConditionalOnMissingBean(<strong>WebMvcConfigurationSupport</strong>.<strong>class</strong>)</li>
<li>5、因此@EnableWebMvc  导致了 <strong>WebMvcAutoConfiguration  没有生效。</strong></li>
</ul>
</li>
</ul>
</li>
</ul>
<h4 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h4><p>场景starter <strong>- xxxxAutoConfiguration - 导入xxx组件 - 绑定xxxProperties -</strong> 绑定配置文件项</p>
<h3 id="Thymeleaf"><a href="#Thymeleaf" class="headerlink" title="Thymeleaf"></a>Thymeleaf</h3><h4 id="名称空间"><a href="#名称空间" class="headerlink" title="名称空间"></a>名称空间</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">xmlns:th</span>=<span class="string">&quot;http://www.thymeleaf.org&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="表单提交"><a href="#表单提交" class="headerlink" title="表单提交"></a>表单提交</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--错误信息提示--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">label</span> <span class="attr">style</span>=<span class="string">&quot;color: red&quot;</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;msg&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">label</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">method</span>=<span class="string">&quot;post&quot;</span> <span class="attr">th:action</span>=<span class="string">&quot;@&#123;/login&#125;&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">name</span>=<span class="string">&quot;userName&quot;</span> <span class="attr">placeholder</span>=<span class="string">&quot;请输入用户名&quot;</span> <span class="attr">autofocus</span> <span class="attr">required</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;password&quot;</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span> <span class="attr">placeholder</span>=<span class="string">&quot;请输入密码&quot;</span> <span class="attr">required</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">button</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span>&gt;</span>提交<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="提取公共页面"><a href="#提取公共页面" class="headerlink" title="提取公共页面"></a>提取公共页面</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">xmlns:th</span>=<span class="string">&quot;http://www.thymeleaf.org&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span> <span class="attr">th:fragment</span>=<span class="string">&quot;commonheader&quot;</span>&gt;</span></span><br><span class="line">    公共的头</span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">th:fragment</span>=<span class="string">&quot;table&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h3</span>&gt;</span>公共页面跳转部分<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">th:href</span>=<span class="string">&quot;@&#123;/table1&#125;&quot;</span>&gt;</span>table1<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">th:href</span>=<span class="string">&quot;@&#123;/table2&#125;&quot;</span>&gt;</span>table2<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">th:href</span>=<span class="string">&quot;@&#123;/table3&#125;&quot;</span>&gt;</span>table3<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>table1.html</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">xmlns:th</span>=<span class="string">&quot;http://www.thymeleaf.org&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>table1<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">th:include</span>=<span class="string">&quot;common :: commonheader&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">h1</span>&gt;</span>table1页面<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">p</span>&gt;</span>欢迎用户：[[$&#123;session.loginUser.userName&#125;]]<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">th:replace</span>=<span class="string">&quot;common :: table&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">table</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">th</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span>&gt;</span>用户名<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span>&gt;</span>密码<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">th</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">tr</span> <span class="attr">th:each</span>=<span class="string">&quot;user,states:$&#123;users&#125;&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;states.count&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;user.userName&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span>&gt;</span>[[$&#123;user.password&#125;]]<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">table</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="分页"><a href="#分页" class="headerlink" title="分页"></a>分页</h4><p>table3（使用MyBatis-Plus）</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">table</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">th</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">td</span>&gt;</span>id<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">td</span>&gt;</span>用户名<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">td</span>&gt;</span>年龄<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">td</span>&gt;</span>邮箱<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">th</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">tr</span> <span class="attr">th:each</span>=<span class="string">&quot;user,states:$&#123;page.records&#125;&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;states.count&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;user.id&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;user.name&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span> <span class="attr">th:text</span>=<span class="string">&quot;$&#123;user.age&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span>&gt;</span>[[$&#123;user.email&#125;]]<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">td</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">a</span> <span class="attr">th:href</span>=<span class="string">&quot;@&#123;/user/delete/&#123;id&#125;(id=$&#123;user.id&#125;,pn=$&#123;page.current&#125;)&#125;&quot;</span>&gt;</span>删除<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">table</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">    当前第[[$&#123;page.current&#125;]]页，总计[[$&#123;page.pages&#125;]]页，共[[$&#123;page.total&#125;]]条记录</span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">th:each</span>=<span class="string">&quot;num:$&#123;#numbers.sequence(1,page.pages)&#125;&quot;</span> <span class="attr">th:style</span>=<span class="string">&quot;$&#123;num==page.current?&#x27;color: red&#x27;:&#x27;&#x27;&#125;&quot;</span></span></span><br><span class="line"><span class="tag">   <span class="attr">th:href</span>=<span class="string">&quot;@&#123;/table3(pn=$&#123;num&#125;)&#125;&quot;</span>&gt;</span>[[$&#123;num&#125;]] |<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>需要在容器注入拦截器</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> MybatisPlusInterceptor <span class="title">paginationInterceptor</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    MybatisPlusInterceptor mybatisPlusInterceptor = <span class="keyword">new</span> MybatisPlusInterceptor();</span><br><span class="line">    <span class="comment">// 设置请求的页面大于最大页后操作， true调回到首页，false 继续请求  默认false</span></span><br><span class="line">    <span class="comment">// paginationInterceptor.setOverflow(false);</span></span><br><span class="line">    <span class="comment">// 设置最大单页限制数量，默认 500 条，-1 不受限制</span></span><br><span class="line">    <span class="comment">// paginationInterceptor.setLimit(500);</span></span><br><span class="line">    <span class="comment">// 开启 count 的 join 优化,只针对部分 left join</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 分页拦截器</span></span><br><span class="line">    PaginationInnerInterceptor paginationInnerInterceptor = <span class="keyword">new</span> PaginationInnerInterceptor();</span><br><span class="line">    paginationInnerInterceptor.setOverflow(<span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line">    mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);</span><br><span class="line">    <span class="keyword">return</span> mybatisPlusInterceptor;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>对应的Controller</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@GetMapping(&quot;/table3&quot;)</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">table3</span><span class="params">(Model model, <span class="meta">@RequestParam(value = &quot;pn&quot;, defaultValue = &quot;1&quot;)</span> Integer pn)</span> </span>&#123;</span><br><span class="line">    Page&lt;User&gt; userPage = <span class="keyword">new</span> Page&lt;&gt;(pn, <span class="number">2</span>);</span><br><span class="line">    Page&lt;User&gt; page = userService.page(userPage, <span class="keyword">null</span>);</span><br><span class="line">    model.addAttribute(<span class="string">&quot;page&quot;</span>, page);</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;table/table3&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@GetMapping(&quot;/user/delete/&#123;id&#125;&quot;)</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">deleteUser</span><span class="params">(<span class="meta">@PathVariable(&quot;id&quot;)</span> Long id,</span></span></span><br><span class="line"><span class="function"><span class="params">                         <span class="meta">@RequestParam(value = &quot;pn&quot;, defaultValue = &quot;1&quot;)</span> Integer pn,</span></span></span><br><span class="line"><span class="function"><span class="params">                         RedirectAttributes ra)</span> </span>&#123;</span><br><span class="line">    userService.removeById(id);</span><br><span class="line">    ra.addAttribute(<span class="string">&quot;pn&quot;</span>, pn);</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;redirect:/table3&quot;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="Restful风格"><a href="#Restful风格" class="headerlink" title="Restful风格"></a>Restful风格</h3><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">action</span>=<span class="string">&quot;/student&quot;</span> <span class="attr">method</span>=<span class="string">&quot;get&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">value</span>=<span class="string">&quot;REST-GET 提交&quot;</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">action</span>=<span class="string">&quot;/student&quot;</span> <span class="attr">method</span>=<span class="string">&quot;post&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">value</span>=<span class="string">&quot;REST-POST&quot;</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">action</span>=<span class="string">&quot;/student&quot;</span> <span class="attr">method</span>=<span class="string">&quot;post&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;hidden&quot;</span> <span class="attr">name</span>=<span class="string">&quot;_method&quot;</span> <span class="attr">value</span>=<span class="string">&quot;PUT&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">value</span>=<span class="string">&quot;REST-PUT&quot;</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">form</span> <span class="attr">action</span>=<span class="string">&quot;/student&quot;</span> <span class="attr">method</span>=<span class="string">&quot;post&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;hidden&quot;</span> <span class="attr">name</span>=<span class="string">&quot;_method&quot;</span> <span class="attr">value</span>=<span class="string">&quot;DELETE&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">input</span> <span class="attr">value</span>=<span class="string">&quot;REST-DELETE&quot;</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@GetMapping(value = &#123;&quot;/&quot;, &quot;/login&quot;&#125;)</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">loginPage</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;login&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@PostMapping(&quot;/login&quot;)</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">main</span><span class="params">(User user, HttpSession session, Model model)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (!StringUtils.isEmpty(user.getUserName()) &amp;&amp; <span class="string">&quot;123456&quot;</span>.equals(user.getPassword())) &#123;</span><br><span class="line">        session.setAttribute(<span class="string">&quot;loginUser&quot;</span>, user);</span><br><span class="line">        <span class="comment">// 避免表单重复提交</span></span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;redirect:/main.html&quot;</span>;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        model.addAttribute(<span class="string">&quot;msg&quot;</span>, <span class="string">&quot;账号密码错误&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;login&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="MyBatis"><a href="#MyBatis" class="headerlink" title="MyBatis"></a>MyBatis</h2><p>若Mapper文件不想每个都写@Mapper，只需在SpringBootApplication添加包扫描注解</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@MapperScan(&quot;com.org.mapper&quot;)</span></span><br></pre></td></tr></table></figure>

<p>在application.yml配置MyBatis</p>
<figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">mybatis:</span></span><br><span class="line">  <span class="attr">mapper-locations:</span> <span class="string">classpath:mybatis/mapper/*.xml</span></span><br><span class="line">  <span class="attr">configuration:</span> <span class="comment"># 相当于mybatis.xml全局配置文件</span></span><br><span class="line">    <span class="attr">map-underscore-to-camel-case:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure>

<h3 id="注解和配置文件写法"><a href="#注解和配置文件写法" class="headerlink" title="注解和配置文件写法"></a>注解和配置文件写法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Select(&quot;select * from t_user where uid = #&#123;uid&#125;&quot;)</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> User <span class="title">getUser</span><span class="params">(Integer uid)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">insertUser</span><span class="params">(User user)</span></span>;</span><br></pre></td></tr></table></figure>

<p>映射文件</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">mapper</span></span></span><br><span class="line"><span class="meta">        <span class="meta-keyword">PUBLIC</span> <span class="meta-string">&quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;</span></span></span><br><span class="line"><span class="meta">        <span class="meta-string">&quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">&quot;com.org.mapper.UserMapper&quot;</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--    &amp;lt;!&amp;ndash;public User getUser(Integer uid);&amp;ndash;&amp;gt;--&gt;</span></span><br><span class="line"><span class="comment">&lt;!--    &lt;select id=&quot;getUser&quot; resultType=&quot;com.org.bean.User&quot;&gt;--&gt;</span></span><br><span class="line"><span class="comment">&lt;!--        select * from t_user where uid = #&#123;uid&#125;--&gt;</span></span><br><span class="line"><span class="comment">&lt;!--    &lt;/select&gt;--&gt;</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">&lt;!--    public void insertUser(User user);--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">insert</span> <span class="attr">id</span>=<span class="string">&quot;insertUser&quot;</span> <span class="attr">useGeneratedKeys</span>=<span class="string">&quot;true&quot;</span> <span class="attr">keyProperty</span>=<span class="string">&quot;uid&quot;</span>&gt;</span></span><br><span class="line">        insert into t_user(user_name,password) values (#&#123;userName&#125;,#&#123;password&#125;)</span><br><span class="line">    <span class="tag">&lt;/<span class="name">insert</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">mapper</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="实体类属性名和表的字段名不同"><a href="#实体类属性名和表的字段名不同" class="headerlink" title="实体类属性名和表的字段名不同"></a>实体类属性名和表的字段名不同</h3><ul>
<li>写sql语句起别名</li>
<li>在MyBatis配置文件增加settings标签，在setting设置mapUnderscoreToCamelCase为true</li>
<li>在Mapper映射文件使用resultMap自定义映射规则</li>
</ul>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">type</span>=<span class="string">&quot;全类名&quot;</span>, <span class="attr">id</span>=<span class="string">&quot;resultMap的名字&quot;</span>,&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 映射主键 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">id</span> <span class="attr">column</span>=<span class="string">&quot;table_id&quot;</span> <span class="attr">property</span>=<span class="string">&quot;id&quot;</span>/&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 映射其他列 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;table_name&quot;</span> <span class="attr">property</span>=<span class="string">&quot;name&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="MyBatis-Plus"><a href="#MyBatis-Plus" class="headerlink" title="MyBatis-Plus"></a>MyBatis-Plus</h2><p>UserMapper继承BaseMapper<T></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">UserMapper</span> <span class="keyword">extends</span> <span class="title">BaseMapper</span>&lt;<span class="title">User</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>UserService继承IService<T></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">UserService</span> <span class="keyword">extends</span> <span class="title">IService</span>&lt;<span class="title">User</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>UserServiceImpl继承ServiceImpl&lt;M extends BaseMapper<T>, T&gt;，并实现UserService接口</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserServiceImpl</span> <span class="keyword">extends</span> <span class="title">ServiceImpl</span>&lt;<span class="title">UserMapper</span>, <span class="title">User</span>&gt; <span class="keyword">implements</span> <span class="title">UserService</span></span></span><br></pre></td></tr></table></figure>

<p>默认表名为Bean对应的表，可在Bean添加表名注解</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@TableName(&quot;user&quot;)</span></span><br></pre></td></tr></table></figure>



<h2 id="Shiro"><a href="#Shiro" class="headerlink" title="Shiro"></a>Shiro</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.org.config;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.apache.shiro.spring.web.ShiroFilterFactoryBean;</span><br><span class="line"><span class="keyword">import</span> org.apache.shiro.web.mgt.DefaultWebSecurityManager;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Qualifier;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Bean;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Configuration;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.LinkedHashMap;</span><br><span class="line"><span class="keyword">import</span> java.util.Map;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ShiroConfig</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//第三步：ShiroFilterFactoryBean</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> ShiroFilterFactoryBean <span class="title">getShiroFilterFactoryBean</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">            <span class="meta">@Qualifier(&quot;getDefaultWebSecurityManager&quot;)</span> DefaultWebSecurityManager securityManager)</span> </span>&#123;</span><br><span class="line">        ShiroFilterFactoryBean shiroFilterFactoryBean = <span class="keyword">new</span> ShiroFilterFactoryBean();</span><br><span class="line">        <span class="comment">//设置安全管理器</span></span><br><span class="line">        shiroFilterFactoryBean.setSecurityManager(securityManager);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//添加过滤器</span></span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">         * * 常见过滤器：</span></span><br><span class="line"><span class="comment">         * anon：无需认证（登录）可以访问</span></span><br><span class="line"><span class="comment">         * authc：必须认证才可以访问</span></span><br><span class="line"><span class="comment">         * user:如果使用Remember Me的功能，可以直接访问</span></span><br><span class="line"><span class="comment">         * perms:该资源必须得到资源权限才可以访问</span></span><br><span class="line"><span class="comment">         * role:该资源必须得到角色权限才可以访问</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        Map&lt;String, String&gt; filterChainDefinitionMap = <span class="keyword">new</span> LinkedHashMap&lt;&gt;();</span><br><span class="line"></span><br><span class="line">        <span class="comment">//授权</span></span><br><span class="line">        filterChainDefinitionMap.put(<span class="string">&quot;/user/add&quot;</span>,<span class="string">&quot;perms[user:add]&quot;</span>);</span><br><span class="line">        filterChainDefinitionMap.put(<span class="string">&quot;/user/*&quot;</span>,<span class="string">&quot;authc&quot;</span>); <span class="comment">//注意顺序</span></span><br><span class="line">        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//设置登录请求</span></span><br><span class="line">        shiroFilterFactoryBean.setLoginUrl(<span class="string">&quot;/login&quot;</span>);</span><br><span class="line">        <span class="comment">//未授权页面</span></span><br><span class="line">        shiroFilterFactoryBean.setUnauthorizedUrl(<span class="string">&quot;/unauth&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> shiroFilterFactoryBean;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//第二步：DefaultWebSecurityManager</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> DefaultWebSecurityManager <span class="title">getDefaultWebSecurityManager</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params">            <span class="meta">@Qualifier(&quot;userRealm&quot;)</span> UserRealm userRealm)</span> </span>&#123;</span><br><span class="line">        DefaultWebSecurityManager securityManager = <span class="keyword">new</span> DefaultWebSecurityManager();</span><br><span class="line">        <span class="comment">//关联realm对象（不能调用下面的方法，要从容器中获取，Qualifer默认参数为方法名）</span></span><br><span class="line">        securityManager.setRealm(userRealm);</span><br><span class="line">        <span class="keyword">return</span> securityManager;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//第一步：创建realm对象，需要自定义类</span></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> UserRealm <span class="title">userRealm</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> UserRealm();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>UserRealm</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.org.config;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;</span><br><span class="line"><span class="keyword">import</span> com.org.bean.TUser;</span><br><span class="line"><span class="keyword">import</span> com.org.service.TUserService;</span><br><span class="line"><span class="keyword">import</span> org.apache.shiro.SecurityUtils;</span><br><span class="line"><span class="keyword">import</span> org.apache.shiro.authc.*;</span><br><span class="line"><span class="keyword">import</span> org.apache.shiro.authz.AuthorizationInfo;</span><br><span class="line"><span class="keyword">import</span> org.apache.shiro.authz.SimpleAuthorizationInfo;</span><br><span class="line"><span class="keyword">import</span> org.apache.shiro.realm.AuthorizingRealm;</span><br><span class="line"><span class="keyword">import</span> org.apache.shiro.subject.PrincipalCollection;</span><br><span class="line"><span class="keyword">import</span> org.apache.shiro.subject.Subject;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserRealm</span> <span class="keyword">extends</span> <span class="title">AuthorizingRealm</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    TUserService userService;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//授权</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> AuthorizationInfo <span class="title">doGetAuthorizationInfo</span><span class="params">(PrincipalCollection principalCollection)</span> </span>&#123;</span><br><span class="line">        SimpleAuthorizationInfo info = <span class="keyword">new</span> SimpleAuthorizationInfo();</span><br><span class="line">        info.addStringPermission(<span class="string">&quot;user:add&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//当前登陆对象</span></span><br><span class="line">        Subject subject = SecurityUtils.getSubject();</span><br><span class="line">        TUser tUser = (TUser) subject.getPrincipal();<span class="comment">//取认证的返回值</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">//设置用户权限</span></span><br><span class="line">        info.addStringPermission(tUser.getPerms());</span><br><span class="line">        <span class="keyword">return</span> info;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//认证</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> AuthenticationInfo <span class="title">doGetAuthenticationInfo</span><span class="params">(AuthenticationToken authenticationToken)</span> <span class="keyword">throws</span> AuthenticationException </span>&#123;</span><br><span class="line"></span><br><span class="line">        UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//验证用户名和密码</span></span><br><span class="line">        QueryWrapper&lt;TUser&gt; queryWrapper = <span class="keyword">new</span> QueryWrapper&lt;&gt;();</span><br><span class="line">        queryWrapper.select(userToken.getUsername());</span><br><span class="line">        TUser tUser = userService.getOne(queryWrapper);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (tUser == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>; <span class="comment">//抛出UnknownAccountException异常</span></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//密码认证</span></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> SimpleAuthenticationInfo(tUser, tUser.getPassword(), <span class="string">&quot;&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="Swagger"><a href="#Swagger" class="headerlink" title="Swagger"></a>Swagger</h2><p><strong>用于前后端分离的api文档</strong></p>
<p>导入依赖</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--swagger--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>io.springfox<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>springfox-swagger2<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.9.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>io.springfox<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>springfox-swagger-ui<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.9.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>配置类</p>
<p>配置多个组只需配多个Docket实例即可</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="meta">@EnableSwagger2</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SwaggerConfig</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Docket <span class="title">docket</span><span class="params">(Environment environment)</span> </span>&#123;</span><br><span class="line">        Profiles profiles = Profiles.of(<span class="string">&quot;dev&quot;</span>);</span><br><span class="line">        <span class="keyword">boolean</span> flag = environment.acceptsProfiles(profiles);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> Docket(DocumentationType.SWAGGER_2)</span><br><span class="line">                .apiInfo(apiInfo())</span><br><span class="line">                .enable(flag)</span><br><span class="line">                .select()</span><br><span class="line">                <span class="comment">//自定义扫描包</span></span><br><span class="line">                .apis(RequestHandlerSelectors.basePackage(<span class="string">&quot;com.org.controller&quot;</span>))</span><br><span class="line">                .build();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> ApiInfo <span class="title">apiInfo</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        Contact contact = <span class="keyword">new</span> Contact(<span class="string">&quot;余振鑫&quot;</span>, <span class="string">&quot;localhost:8080&quot;</span>, <span class="string">&quot;1399079216@qq.com&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> ApiInfo(</span><br><span class="line">                <span class="string">&quot;我的测试系统api文档&quot;</span>,</span><br><span class="line">                <span class="string">&quot;第一次使用swagger自动生成文档&quot;</span>,</span><br><span class="line">                <span class="string">&quot;1.0&quot;</span>,</span><br><span class="line">                <span class="string">&quot;http://localhost:8080&quot;</span>,</span><br><span class="line">                contact,</span><br><span class="line">                <span class="string">&quot;Apache 2.0&quot;</span>,</span><br><span class="line">                <span class="string">&quot;http://www.apache.org/licenses/LICENSE-2.0&quot;</span>,</span><br><span class="line">                <span class="keyword">new</span> ArrayList()</span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>2.x访问方式：<strong>注意端口号！</strong></p>
<p><a target="_blank" rel="noopener" href="http://localhost:8080/swagger-ui.html">http://localhost:8080/swagger-ui.html</a></p>
<p>swagger 3.0的版本访问方式</p>
<p><a target="_blank" rel="noopener" href="http://localhost:8080/swagger-ui/index.html">http://localhost:8080/swagger-ui/index.html</a></p>
<h2 id="JWT"><a href="#JWT" class="headerlink" title="JWT"></a>JWT</h2><p>jwt由三个部分组成：</p>
<ul>
<li>header</li>
<li>payload</li>
<li>签名</li>
</ul>
<p>Jheader = Base64(header)</p>
<p>Jpayload = Base64(payload)</p>
<p>J签名 = MD5(payload + 密钥/盐值)</p>
<p><strong>JWT = Jheader.Jpayload.J签名</strong></p>
<h3 id="验证签名"><a href="#验证签名" class="headerlink" title="验证签名"></a>验证签名</h3><p>判断<strong>MD5(Base64.decode(JWT.split(“.”)[1]) + 密钥/盐值)<strong>和</strong>J签名</strong>是否相等</p>
<h2 id="EasyExcel"><a href="#EasyExcel" class="headerlink" title="EasyExcel"></a>EasyExcel</h2><blockquote>
<p><a target="_blank" rel="noopener" href="https://www.yuque.com/easyexcel/doc/easyexcel">https://www.yuque.com/easyexcel/doc/easyexcel</a></p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 下载的response处理</span></span><br><span class="line">response.setContentType(<span class="string">&quot;application/vnd.ms-excel&quot;</span>);</span><br><span class="line">response.setCharacterEncoding(<span class="string">&quot;utf-8&quot;</span>);</span><br><span class="line">String fileName = URLEncoder.encode(<span class="string">&quot;IM首次回复率&quot;</span>, StandardCharsets.UTF_8);</span><br><span class="line">response.setHeader(<span class="string">&quot;fileName&quot;</span>, fileName + <span class="string">&quot;.xlsx&quot;</span>);</span><br><span class="line">EasyExcel.write(response.getOutputStream(), FirstResponseRateRespDto.class).sheet(<span class="string">&quot;IM首次回复率&quot;</span>).doWrite(firstResponseRateRespDtoList);</span><br></pre></td></tr></table></figure>



<h2 id="一些知识点"><a href="#一些知识点" class="headerlink" title="一些知识点"></a>一些知识点</h2><ul>
<li><p>URL命名：</p>
<ul>
<li>prefix：横杠</li>
<li>path：下划线</li>
<li>参数名：下划线</li>
</ul>
<p>如：<a target="_blank" rel="noopener" href="https://www.yuzhenxin-web.com/api/v1/my_info?user_id=12345">https://www.yuzhenxin-web.com/api/v1/my_info?user_id=12345</a></p>
</li>
<li><p>@JsonProperty是和前端交互</p>
</li>
<li><p>dto的属性名称和数据库交互，必须使用驼峰（除非用@TableName），取数据库别名（下划线或驼峰都可）</p>
</li>
</ul>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://yuzhenxin.gitee.io/2020/12/23/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="余振鑫">
      <meta itemprop="description" content="余振鑫的个人博客">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="余振鑫的Hexo博客">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2020/12/23/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/" class="post-title-link" itemprop="url">计算机基础</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-12-23 00:00:00" itemprop="dateCreated datePublished" datetime="2020-12-23T00:00:00+08:00">2020-12-23</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2021-04-07 08:31:31" itemprop="dateModified" datetime="2021-04-07T08:31:31+08:00">2021-04-07</time>
              </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="计算机基础"><a href="#计算机基础" class="headerlink" title="计算机基础"></a>计算机基础</h1><h2 id="数据结构"><a href="#数据结构" class="headerlink" title="数据结构"></a>数据结构</h2><h3 id="树"><a href="#树" class="headerlink" title="树"></a>树</h3><ul>
<li>k叉树n0个叶结点要构成哈夫曼树需要补充(n0-1)%(k-1)个叶结点，结果的带权路径长度WPL=nk</li>
<li>树的先序遍历对应二叉树（根节点无右孩子）的先序遍历，树的后序遍历对应二叉树的中序遍历</li>
<li>森林的先序遍历对应二叉树的先序遍历，森林的后序遍历（也是中序遍历）对应二叉树的中序遍历</li>
<li>二叉树的先序遍历相当于入栈，中序遍历相当于出栈。（根左右的顺序，先序遍历就需要先访问根节点，入栈访问，中序遍历先访问左孩子，故出栈访问根节点）</li>
<li>二叉树转森林，断开右孩子，左孩子右兄弟</li>
<li>n0 = 1+n2+2n3+…</li>
<li>LL调整：新插入结点落在最小不平衡子树根节点的左孩子的左子树上</li>
<li>图的广度优先遍历相当于二叉树的层次遍历，深度优先遍历相当于二叉树的先序遍历</li>
<li>两个长度为m、n的升序链表合并为一个升/降序链表（尾插法和头插法），时间复杂度最好O(min(m,n))，最坏O(max(m,n))</li>
<li>B树根节点（非叶子结点）至少2个分支（一个关键字），非根非叶结点至少m/2取上界-1个关键字，至多k-1个关键字（k叉B树）</li>
</ul>
<h4 id="二叉排序树"><a href="#二叉排序树" class="headerlink" title="二叉排序树"></a>二叉排序树</h4><ol>
<li><strong>左</strong>子树上所有结点的值均<strong>小于或等于</strong>它的根结点的值。</li>
<li><strong>右</strong>子树上所有结点的值均<strong>大于或等于</strong>它的根结点的值。</li>
<li>左、右子树也分别为二叉排序树。</li>
</ol>
<h4 id="平衡二叉树"><a href="#平衡二叉树" class="headerlink" title="平衡二叉树"></a>平衡二叉树</h4><p>平衡二叉树又称AVL树，它是一种<strong>特殊的二叉排序树</strong>：它的左子树和右子树都是平衡二叉树，且左子树和右子树的深度之差的绝对值不超过1。使用了二分查找的思想，查找所需的最大次数等同于二叉查找树的高度。</p>
<h5 id="调整"><a href="#调整" class="headerlink" title="调整"></a>调整</h5><ul>
<li><p>RR平衡旋转：左旋</p>
<p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210317212320.png" alt="image-20210317212313023"></p>
</li>
<li><p>LL平衡旋转：右旋</p>
</li>
<li><p>RL平衡旋转：先右旋再左旋</p>
<p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210317212403.png" alt="image-20210317212403292"></p>
</li>
<li><p>LR平衡旋转：先左旋再右旋</p>
</li>
</ul>
<h4 id="红黑树"><a href="#红黑树" class="headerlink" title="红黑树"></a>红黑树</h4><ul>
<li>节点是红色或黑色。</li>
<li>根节点是黑色。</li>
<li>每个叶子节点都是黑色的空节点（NIL节点）。</li>
<li>每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)</li>
<li>从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。</li>
<li><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210311230819.png" alt="image-20210311230819057"></li>
</ul>
<h3 id="堆"><a href="#堆" class="headerlink" title="堆"></a>堆</h3><ul>
<li><p>堆中某个节点的值总是不大于或不小于其父节点的值</p>
</li>
<li><p>堆总是一棵完全二叉树</p>
</li>
<li><p>堆排序删除该轮最大结点（大根堆的根节点）后，将底层最右边的结点移到根节点</p>
</li>
</ul>
<h3 id="散列表"><a href="#散列表" class="headerlink" title="散列表"></a>散列表</h3><ul>
<li>散列表查找成功ASL=几次找到元素/元素个数，查找失败ASL=几次找到空指针/可用表长（模数）</li>
</ul>
<h3 id="串"><a href="#串" class="headerlink" title="串"></a>串</h3><ul>
<li>KMP的nextval，当前值与next对应的值是否相同，相同就抄对方的nextval，不同就照抄next</li>
</ul>
<h3 id="排序"><a href="#排序" class="headerlink" title="排序"></a>排序</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 快速排序</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">Partition</span><span class="params">(<span class="keyword">int</span> A[], <span class="keyword">int</span> low, <span class="keyword">int</span> high)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> pivot = A[low]; <span class="comment">//将数组以A[low]划分左右</span></span><br><span class="line">    <span class="keyword">while</span> (low &lt; high) &#123;</span><br><span class="line">        <span class="comment">//在low的右侧找到第一个小于中轴的数</span></span><br><span class="line">        <span class="keyword">while</span> (low &lt; high &amp;&amp; A[high] &gt;= pivot) --high;</span><br><span class="line">        <span class="comment">//把这个数放到low处</span></span><br><span class="line">        A[low] = A[high];</span><br><span class="line">        <span class="comment">//在high的左侧找到第一个大于中轴的数</span></span><br><span class="line">        <span class="keyword">while</span> (low &lt; high &amp;&amp; A[low] &lt;= pivot) ++low;</span><br><span class="line">        <span class="comment">//把这个数放到high处</span></span><br><span class="line">        A[high] = A[low];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//low和high相遇时为划分左右的中轴</span></span><br><span class="line">    A[low] = pivot;</span><br><span class="line">    <span class="keyword">return</span> low;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//low和high为头尾元素下标</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">QuickSort</span><span class="params">(<span class="keyword">int</span> A[], <span class="keyword">int</span> low, <span class="keyword">int</span> high)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (low &lt; high) &#123;</span><br><span class="line">        <span class="keyword">int</span> pivot = Partition(A, low, high);</span><br><span class="line">        QuickSort(A, low, pivot - <span class="number">1</span>); <span class="comment">//递归完成左侧排序</span></span><br><span class="line">        QuickSort(A, pivot + <span class="number">1</span>, high); <span class="comment">//递归完成右侧排序</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="计算机组成原理"><a href="#计算机组成原理" class="headerlink" title="计算机组成原理"></a>计算机组成原理</h2><ul>
<li>补码（8位：-128~127）<ul>
<li>1000 0000作为补码的真值为-1或-128（-2^7）（负数的话不看符号位，大的真值就大）</li>
<li>1111 1111作为补码的真值为-1</li>
</ul>
</li>
<li>类型转换通过扩展机器数符号位</li>
<li>算术移位：符号位不动，负数补码左移添0右移添1，原码添0</li>
<li>溢出判断：符号位相同运算而结果符号不同</li>
<li>X的补码全反+1=-X的补码</li>
<li>补码一位乘法：最多n次移位，n+1次加法；原码运算符号位都单独出来，乘除结果符号位由异或得到；原码不恢复余数法（加减交替法）只在最终余数为负才恢复余数；补码除法，异号相除看够不够减，够减商0，不够商1</li>
<li>float的阶码1~254，偏移值-127</li>
<li>中断隐指令保存PC断点</li>
<li>Cache附加位：有效位、访问位、脏位；LRU的位数取决于log2(几路组相联)。</li>
</ul>
<h2 id="操作系统"><a href="#操作系统" class="headerlink" title="操作系统"></a>操作系统</h2><ul>
<li><p>用户发出open系统调用，提供文件名和访问路径参数；操作系统从外存调入FCB，返回用户文件描述符（指针），用户通过文件描述符找到FCB，调用read系统调用将数据读入内存。</p>
</li>
<li><p>管程相当于类，条件变量类似信号量，但是没有值，因此只能用于排队：阻塞（wait）或唤醒（signal），编译器实现对条件变量的互斥访问</p>
</li>
<li><p>只有FIFO可能会发生Belady异常</p>
</li>
<li><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307224133.png" alt="image-20210130113735311" style="zoom:200%;" /></li>
<li><p>目录文件每一项包含文件名和索引结点指针，索引指针指向的索引结点包含文件属性和地址信息</p>
<p>文件分配基本单位是簇/块</p>
</li>
</ul>
<h2 id="计算机网络"><a href="#计算机网络" class="headerlink" title="计算机网络"></a>计算机网络</h2><p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307224158.png" alt="image-20210130114348957"></p>
<p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307224206.png" alt="image-20210130114200617"></p>
<p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307224216.png" alt="image-20210130114205071"></p>
<p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307224226.png" alt="image-20210130114255062"></p>
<p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307224234.png" alt="image-20210130114309796"></p>
<p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307224242.png" alt="image-20210130114313547"></p>
<p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307224249.png" alt="image-20210130114315859"></p>
<h3 id="TCP和UDP区别"><a href="#TCP和UDP区别" class="headerlink" title="TCP和UDP区别"></a>TCP和UDP区别</h3><p>TCP（TransmissionControl Protocol 传输控制协议）是一种面向连接的、可靠的、基于字节流的传输层通信协议。</p>
<p>UDP是User Datagram Protocol，一种无连接的传输层协议，提供面向事务的简单不可靠信息传送服务。可靠性由上层应用实现，所以要实现udp可靠性传输，必须通过应用层来实现和控制。</p>
<h3 id="TCP三次握手和四次挥手过程及原因"><a href="#TCP三次握手和四次挥手过程及原因" class="headerlink" title="TCP三次握手和四次挥手过程及原因"></a>TCP三次握手和四次挥手过程及原因</h3><h4 id="三次握手过程"><a href="#三次握手过程" class="headerlink" title="三次握手过程"></a>三次握手过程</h4><p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210320152831.png" alt="image-20210320152824133"></p>
<ol>
<li>客户机向服务器发送连接请求，SYN和序列号seq（随机生成），进入SYN-SENT状态。</li>
<li>服务器接到请求后，发送确认ACK和同步信号SYN，还有序列号seq，进入SYN-RCVD状态</li>
<li>客户机再向服务器发送确认报文，ACK和seq，进入ESTABLISHED状态。此阶段可以携带报文，不携带则不消耗序列号</li>
</ol>
<h4 id="三次握手的原因"><a href="#三次握手的原因" class="headerlink" title="三次握手的原因"></a>三次握手的原因</h4><p>为了防止已失效的请求突然发送到服务器，产生错误。</p>
<ul>
<li>假设两次握手时客户机发送的第一个连接请求报文滞留到连接释放后才发送到服务器，B会以为又是一个新的连接请求，发送确认报文段，两次握手下就建立了连接，浪费资源。</li>
<li>假设客户机发送连接请求后就下线，服务器收到请求就会发送确认报文段，建立连接，浪费资源。</li>
</ul>
<h4 id="四次挥手过程"><a href="#四次挥手过程" class="headerlink" title="四次挥手过程"></a>四次挥手过程</h4><p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210320152842.png" alt="image-20210320152842153"></p>
<ol>
<li>客户机向服务器发送连接释放报文，FIN和seq，进入FIN-WAIT1状态。</li>
<li>服务器收到释放报文就发送确认报文，ACK和seq，进入CLOSE-WAIT状态。此时TCP连接处于半关闭状态，B仍可以发送给A数据</li>
<li>A收到B确认后，进入FIN-WAIT2状态，等待B发送连接释放报文</li>
<li>B发完数据后发送释放连接报文，FIN、ACK和seq，进入LAST-ACK状态</li>
<li>A收到连接释放报文就发送确认报文，ACK和seq，进入TIME-WAIT状态</li>
<li>B收到确认报文就进入CLOSED状态。</li>
<li>经过2MSL（最长报文段寿命）后，A进入CLOSED状态，结束。</li>
</ol>
<h4 id="设置TIME-WAIT原因"><a href="#设置TIME-WAIT原因" class="headerlink" title="设置TIME-WAIT原因"></a>设置TIME-WAIT原因</h4><ul>
<li>保证A发送的最后一个ACK能到达B，若丢失，B会超时重传FIN+ACK报文，A就能收到再重传。</li>
<li>A发完最后一个ACK后，经过2MSL就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。</li>
</ul>
<h4 id="四次挥手原因"><a href="#四次挥手原因" class="headerlink" title="四次挥手原因"></a>四次挥手原因</h4><ul>
<li>TCP全双工，关闭连接应由双方共同确认</li>
<li>假设三次挥手，B发送确认报文段就会立刻发送确认报文，会导致B向A还在发送数据时连接就被关闭。这样会导致A没有完整收到B所发的报文段</li>
</ul>
<h3 id="TCP拥塞控制"><a href="#TCP拥塞控制" class="headerlink" title="TCP拥塞控制"></a>TCP拥塞控制</h3><p>在发送数据时，将拥塞窗口的大小与接收端ack的窗口大小做比较，取较小者作为发送数据量的上限</p>
<ol>
<li>慢启动，每经过一个RTT，cwnd = cwnd*2; 呈指数上升</li>
<li>拥塞避免，cwnd达到阈值ssthresh。每当过了一个RTT，cwnd = cwnd + 1</li>
<li>阻塞发生：sshthresh = cwnd /2，cwnd重置为1</li>
<li>快重传，连续收到3个重复确认报文就重传，sshthresh = cwnd = cwnd /2</li>
<li>快恢复，cwnd = cwnd +1</li>
</ol>
<h3 id="从浏览器输入一个URL到返回响应的完整过程"><a href="#从浏览器输入一个URL到返回响应的完整过程" class="headerlink" title="从浏览器输入一个URL到返回响应的完整过程"></a>从浏览器输入一个URL到返回响应的完整过程</h3><ol>
<li>DNS解析<ol>
<li>递归查询本地域名服务器</li>
<li>本地域名服务器迭代访问根域名服务器、顶级域名服务器、权限域名服务器</li>
</ol>
</li>
<li>TCP连接</li>
<li>发送http请求</li>
<li>服务器响应http请求</li>
<li>浏览器解析html</li>
<li>断开TCP连接</li>
</ol>
<h3 id="Https和Http"><a href="#Https和Http" class="headerlink" title="Https和Http"></a>Https和Http</h3><p>HTTP基于TCP，HTTP使用TCP而不是UDP的原因在于（打开）一个网页必须传送很多数据，而TCP协议提供传输控制，按顺序组织数据，和错误纠正。</p>
<p>https协议需要到CA申请证书，一般免费证书很少，需要交费。<br>http是超文本传输协议，信息是明文传输；https 则是具有安全性的ssl加密传输协议。<br>http和https使用的是完全不同的连接方式，用的端口也不一样，前者是80，后者是443。<br>http的连接很简单，是无状态的；HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议，比http协议安全。</p>
<ol>
<li>内容加密：采用混合加密技术，中间者无法直接查看明文内容</li>
<li>验证身份：通过证书认证客户端访问的是自己的服务器</li>
<li>保护数据完整性：防止传输的内容被中间人冒充或者篡改</li>
</ol>
<p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210320161251.png" alt="image-20210320161251368"></p>
<ul>
<li>SSL在握手阶段依赖数字证书建立安全会话<ul>
<li>数字证书包含公钥和数字签名</li>
<li>明文 –&gt; hash运算 –&gt; 摘要 –&gt; 私钥加密 –&gt; 数字签名</li>
</ul>
</li>
<li>传输阶段使用对称加密算法加密（常见：DES、AES）</li>
</ul>
<h3 id="UDP保证可靠性传输"><a href="#UDP保证可靠性传输" class="headerlink" title="UDP保证可靠性传输"></a>UDP保证可靠性传输</h3><p>传输层无法保证数据的可靠传输，只能通过应用层来实现了。实现的方式可以参照tcp可靠性传输的方式，只是实现不在传输层，实现转移到了应用层。</p>
<p>实现确认机制、重传机制、窗口确认机制。</p>
<h3 id="Get和Post"><a href="#Get和Post" class="headerlink" title="Get和Post"></a>Get和Post</h3><ul>
<li>get是获取数据，post是提交数据</li>
<li>GET在浏览器回退时是无害的，而POST会再次提交请求。</li>
<li>GET产生的URL地址可以被Bookmark，而POST不可以。</li>
<li>GET请求会被浏览器主动cache，而POST不会，除非手动设置。</li>
<li>GET请求只能进行url编码，而POST支持多种编码方式。</li>
<li>GET请求参数会被完整保留在浏览器历史记录里，而POST中的参数不会被保留。</li>
<li>GET请求在URL中传送的参数是有长度限制的，而POST么有。</li>
<li>对参数的数据类型，GET只接受ASCII字符，而POST没有限制。</li>
<li>GET比POST更不安全，因为参数直接暴露在URL上，所以不能用来传递敏感信息。</li>
<li>GET参数通过URL传递，POST放在Request body中。</li>
</ul>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://yuzhenxin.gitee.io/2020/11/20/%E6%95%B0%E6%8D%AE%E5%BA%93/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="余振鑫">
      <meta itemprop="description" content="余振鑫的个人博客">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="余振鑫的Hexo博客">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2020/11/20/%E6%95%B0%E6%8D%AE%E5%BA%93/" class="post-title-link" itemprop="url">数据库</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-11-20 00:00:00" itemprop="dateCreated datePublished" datetime="2020-11-20T00:00:00+08:00">2020-11-20</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2022-01-20 19:53:59" itemprop="dateModified" datetime="2022-01-20T19:53:59+08:00">2022-01-20</time>
              </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="数据库"><a href="#数据库" class="headerlink" title="数据库"></a>数据库</h1><h2 id="隔离级别"><a href="#隔离级别" class="headerlink" title="隔离级别"></a>隔离级别</h2><p>数据库事务并发：</p>
<ul>
<li>脏读：读取其他事务更新却没提交的事务（可回滚）<em>自作聪明</em></li>
<li>不可重复读：前后读取字段值不同（中途被其他事务修改）<em>黑客篡改</em></li>
<li>幻读：前后读取多了一些值（中途被其他事务修改）<em>黑客增加数据</em></li>
</ul>
<p>隔离级别：（从上到下级别升高）</p>
<ul>
<li>读未提交READ UNCOMMITTED（都不能避免）</li>
<li>读已提交READ COMMITTED（避免脏读），Oracle默认级别，常用</li>
<li>可重复读REPEATABLE READ（避免脏读和不可重复读）：防止其他事务对该字段更新，MYSQL默认级别</li>
<li>串行化SERIALIZABLE（全部避免）：防任何并发问题，性能很低</li>
</ul>
<h2 id="MySQL"><a href="#MySQL" class="headerlink" title="MySQL"></a>MySQL</h2><h3 id="工作常用到的语句"><a href="#工作常用到的语句" class="headerlink" title="工作常用到的语句"></a>工作常用到的语句</h3><p>between A and B（可以是数字，A 必须小于等于B，否则没有结果）</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 修改主键自增</span></span><br><span class="line"><span class="keyword">ALTER</span> <span class="keyword">TABLE</span> xx MODIFY id <span class="type">bigint</span> auto_increment;</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 清空表内容（可恢复）</span></span><br><span class="line"><span class="keyword">DELETE</span> <span class="keyword">FROM</span> xx;</span><br><span class="line"><span class="comment">-- 清空表内容（不可恢复），相当于删表重建</span></span><br><span class="line"><span class="keyword">TRUNCATE</span> <span class="keyword">TABLE</span> xx;</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 日期格式化</span></span><br><span class="line">date_format(`create_time`,<span class="string">&#x27;%Y%m%d&#x27;</span>)</span><br><span class="line"><span class="comment">-- 毫秒转日期</span></span><br><span class="line">FROM_UNIXTIME(`<span class="type">timestamp</span>`<span class="operator">/</span><span class="number">1000</span>, <span class="string">&#x27;%Y%m%d&#x27;</span>)</span><br><span class="line"><span class="comment">-- 日期转毫秒</span></span><br><span class="line">UNIX_TIMESTAMP(`create_time`) </span><br></pre></td></tr></table></figure>

<h3 id="Dataworks语法"><a href="#Dataworks语法" class="headerlink" title="Dataworks语法"></a>Dataworks语法</h3><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 日期格式化</span></span><br><span class="line">to_char(create_time, <span class="string">&#x27;yyyymmdd&#x27;</span>)</span><br><span class="line"><span class="comment">-- 毫秒转日期</span></span><br><span class="line">to_char(FROM_UNIXTIME(<span class="built_in">CAST</span>(SUBSTR(`<span class="type">timestamp</span>`,<span class="number">-13</span>,<span class="number">10</span>) <span class="keyword">AS</span> <span class="type">BIGINT</span>)),<span class="string">&#x27;yyyymmdd&#x27;</span>)</span><br><span class="line">get_json_object(temp_a.custom_properties,<span class="string">&#x27;$.session_start&#x27;</span>)</span><br></pre></td></tr></table></figure>

<h4 id="表的操作"><a href="#表的操作" class="headerlink" title="表的操作"></a>表的操作</h4><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">create</span> <span class="keyword">table</span> student</span><br><span class="line">(</span><br><span class="line">        s_id <span class="type">int</span>(<span class="number">4</span>) <span class="keyword">not</span> <span class="keyword">null</span> <span class="keyword">PRIMARY</span> KEY auto_increment,</span><br><span class="line">        s_name <span class="type">varchar</span>(<span class="number">12</span>),</span><br><span class="line">        s_age <span class="type">int</span>(<span class="number">4</span>),</span><br><span class="line">        s_sex <span class="type">varchar</span>(<span class="number">2</span>),</span><br><span class="line">        s_date <span class="type">date</span>,</span><br><span class="line">        <span class="keyword">FOREIGN</span> KEY (Id_P) <span class="keyword">REFERENCES</span> Persons(Id_P)</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="keyword">insert</span> <span class="keyword">into</span> Persons <span class="keyword">values</span> (<span class="string">&#x27;Wilson&#x27;</span>, <span class="string">&#x27;Champs-Elysees&#x27;</span>);</span><br><span class="line"><span class="keyword">INSERT</span> <span class="keyword">INTO</span> Persons (LastName, Address) <span class="keyword">VALUES</span> (<span class="string">&#x27;Wilson&#x27;</span>, <span class="string">&#x27;Champs-Elysees&#x27;</span>);</span><br><span class="line"></span><br><span class="line">UPDATE Person <span class="keyword">SET</span> Address <span class="operator">=</span> <span class="string">&#x27;Zhongshan 23&#x27;</span>, City <span class="operator">=</span> <span class="string">&#x27;Nanjing&#x27;</span> <span class="keyword">WHERE</span> LastName <span class="operator">=</span> <span class="string">&#x27;Wilson&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">DELETE</span> <span class="keyword">FROM</span> Person <span class="keyword">WHERE</span> LastName <span class="operator">=</span> <span class="string">&#x27;Wilson&#x27;</span> ;</span><br><span class="line"></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> student s,score c;</span><br><span class="line"><span class="keyword">select</span> s2.s_name,<span class="built_in">count</span>(<span class="operator">*</span>) <span class="keyword">as</span> num <span class="keyword">from</span> score s1 <span class="keyword">INNER</span> <span class="keyword">JOIN</span> student s2 <span class="keyword">on</span> s1.s_no <span class="operator">=</span> s2.s_id <span class="keyword">GROUP</span> <span class="keyword">BY</span> s2.s_name;<span class="comment">--分组查询</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">SELECT</span> Company, OrderNumber <span class="keyword">FROM</span> Orders <span class="keyword">ORDER</span> <span class="keyword">BY</span> OrderNumber <span class="comment">--顺序显示，小-&gt;大</span></span><br><span class="line"><span class="keyword">SELECT</span> Company, OrderNumber <span class="keyword">FROM</span> Orders <span class="keyword">ORDER</span> <span class="keyword">BY</span> OrderNumber <span class="keyword">DESC</span> <span class="comment">--逆序显示，大-&gt;小</span></span><br><span class="line"><span class="comment">-- 聚集函数</span></span><br><span class="line"><span class="keyword">select</span> Sno,<span class="built_in">avg</span>(grade) <span class="keyword">as</span> 平均分 <span class="keyword">from</span> sc <span class="keyword">where</span> Sno<span class="operator">=</span>&quot;171303&quot;;</span><br><span class="line"><span class="keyword">select</span> <span class="built_in">count</span>(<span class="keyword">distinct</span> Sno) <span class="keyword">as</span> 选修学生总数 <span class="keyword">from</span> sc; </span><br><span class="line"><span class="keyword">select</span> <span class="built_in">max</span>(Grade) <span class="keyword">as</span> 最高分,<span class="built_in">min</span>(Grade)<span class="keyword">as</span> 最低分 <span class="keyword">from</span> sc;</span><br><span class="line"><span class="keyword">select</span> <span class="built_in">sum</span>(Grade) <span class="keyword">as</span> 总分 <span class="keyword">from</span> sc;</span><br><span class="line"><span class="comment">-- 分组查询</span></span><br><span class="line"><span class="keyword">select</span> Sdept,<span class="built_in">count</span>(<span class="operator">*</span>) <span class="keyword">as</span> 人数 <span class="keyword">from</span> student <span class="keyword">group</span> <span class="keyword">by</span> Sdept;</span><br><span class="line"><span class="keyword">select</span> Sno,<span class="built_in">avg</span>(Grade) <span class="keyword">as</span> 均分 <span class="keyword">from</span> sc <span class="keyword">group</span> <span class="keyword">by</span> Sno <span class="keyword">having</span> <span class="built_in">avg</span>(Grade)<span class="operator">&gt;</span><span class="number">60</span>;</span><br><span class="line"><span class="comment">-- 等值与非等值查询</span></span><br><span class="line"><span class="keyword">select</span> student.<span class="operator">*</span>,sc.Grade,sc.Cno <span class="keyword">from</span> student,sc <span class="keyword">where</span> student.Sno<span class="operator">=</span>sc.Sno;</span><br></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th>通配符</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td>%</td>
<td>替代一个或多个字符</td>
</tr>
<tr>
<td>_</td>
<td>仅替代一个字符</td>
</tr>
<tr>
<td>[charlist]</td>
<td>字符列中的任何单一字符</td>
</tr>
<tr>
<td>[^charlist]或者[!charlist]</td>
<td>不在字符列中的任何单一字符</td>
</tr>
</tbody></table>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- &quot;Persons&quot; 表中选取居住在以 &quot;N&quot; 开始的城市里的人</span></span><br><span class="line"><span class="keyword">SELECT</span> <span class="operator">*</span> <span class="keyword">FROM</span> Persons <span class="keyword">WHERE</span> City <span class="keyword">LIKE</span> <span class="string">&#x27;N%&#x27;</span>;</span><br><span class="line"><span class="comment">-- 从 &quot;Persons&quot; 表中选取居住在不包含 &quot;lon&quot; 的城市里的人</span></span><br><span class="line"><span class="keyword">SELECT</span> <span class="operator">*</span> <span class="keyword">FROM</span> Persons <span class="keyword">WHERE</span> City <span class="keyword">NOT</span> <span class="keyword">LIKE</span> <span class="string">&#x27;%lon%&#x27;</span>;</span><br><span class="line"><span class="comment">-- &quot;Persons&quot; 表中选取名字的第一个字符之后是 &quot;eorge&quot; 的人</span></span><br><span class="line"><span class="keyword">SELECT</span> <span class="operator">*</span> <span class="keyword">FROM</span> Persons <span class="keyword">WHERE</span> FirstName <span class="keyword">LIKE</span> <span class="string">&#x27;_eorge&#x27;</span>;</span><br><span class="line"><span class="comment">--&quot;Persons&quot; 表中选取居住的城市以 &quot;A&quot; 或 &quot;L&quot; 或 &quot;N&quot; 开头的人</span></span><br><span class="line"><span class="keyword">SELECT</span> <span class="operator">*</span> <span class="keyword">FROM</span> Persons <span class="keyword">WHERE</span> City <span class="keyword">LIKE</span> <span class="string">&#x27;[ALN]%&#x27;</span>;</span><br><span class="line"><span class="comment">--&quot;Persons&quot; 表中选取居住的城市不以 &quot;A&quot; 或 &quot;L&quot; 或 &quot;N&quot; 开头的人</span></span><br><span class="line"><span class="keyword">SELECT</span> <span class="operator">*</span> <span class="keyword">FROM</span> Persons <span class="keyword">WHERE</span> City <span class="keyword">LIKE</span> <span class="string">&#x27;[!ALN]%&#x27;</span>;</span><br></pre></td></tr></table></figure>

<ul>
<li>JOIN: 如果表中有至少一个匹配，则返回行，INNER JOIN 与 JOIN 是相同的。</li>
<li>LEFT JOIN: 即使右表中没有匹配，也从左表返回所有的行</li>
<li>RIGHT JOIN: 即使左表中没有匹配，也从右表返回所有的行</li>
<li>FULL JOIN: 只要其中一个表中存在匹配，就返回行</li>
</ul>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> student s,score c <span class="keyword">where</span> s.s_id <span class="operator">=</span> c.c_id;</span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> student s <span class="keyword">INNER</span> <span class="keyword">JOIN</span> score c <span class="keyword">on</span> s.s_id <span class="operator">=</span> c.s_no; <span class="comment">-- 内连接</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> student s <span class="keyword">LEFT</span> <span class="keyword">JOIN</span> score c <span class="keyword">on</span> s.s_id <span class="operator">=</span> c.s_no; <span class="comment">-- 左连接</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> student s <span class="keyword">RIGHT</span> <span class="keyword">JOIN</span> score c <span class="keyword">on</span> s.s_id <span class="operator">=</span> c.s_no; <span class="comment">-- 右连接</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> student s <span class="keyword">FULL</span> <span class="keyword">JOIN</span> score c <span class="keyword">on</span> s.s_id <span class="operator">=</span> c.s_no;</span><br></pre></td></tr></table></figure>

<h3 id="join"><a href="#join" class="headerlink" title="join"></a>join</h3><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">--内连接，取交集--</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">join</span> score <span class="keyword">on</span> user.id <span class="operator">=</span> score.id;</span><br><span class="line"><span class="comment">--左连接，左边一定要输出，右边匹配输出--</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">left</span> <span class="keyword">join</span> score <span class="keyword">on</span> user.id <span class="operator">=</span> score.id;</span><br><span class="line"><span class="comment">--右连接，右边一定要输出，左边匹配输出--</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">right</span> <span class="keyword">join</span> score <span class="keyword">on</span> user.id <span class="operator">=</span> score.id</span><br><span class="line"><span class="comment">--左右边都要输出，不匹配的为null--</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">left</span> <span class="keyword">join</span> score <span class="keyword">on</span> user.id <span class="operator">=</span> score.id</span><br><span class="line"><span class="keyword">union</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">right</span> <span class="keyword">join</span> score <span class="keyword">on</span> user.id <span class="operator">=</span> score.id;</span><br><span class="line"></span><br><span class="line"><span class="comment">--左边独有的--</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">left</span> <span class="keyword">join</span> score <span class="keyword">on</span> user.id <span class="operator">=</span> score.id <span class="keyword">where</span> score.id <span class="keyword">is</span> <span class="keyword">null</span>;</span><br><span class="line"><span class="comment">--右边独有的--</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">right</span> <span class="keyword">join</span> score <span class="keyword">on</span> user.id <span class="operator">=</span> score.id <span class="keyword">where</span> user.id <span class="keyword">is</span> <span class="keyword">null</span>;</span><br><span class="line"><span class="comment">--左边独有的+右边独有的--</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">left</span> <span class="keyword">join</span> score <span class="keyword">on</span> user.id <span class="operator">=</span> score.id <span class="keyword">where</span> score.id <span class="keyword">is</span> <span class="keyword">null</span></span><br><span class="line"><span class="keyword">union</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">right</span> <span class="keyword">join</span> score <span class="keyword">on</span> user.id <span class="operator">=</span> score.id <span class="keyword">where</span> user.id <span class="keyword">is</span> <span class="keyword">null</span>;</span><br></pre></td></tr></table></figure>

<h4 id="on和where"><a href="#on和where" class="headerlink" title="on和where"></a>on和where</h4><p> on条件是在生成临时表时使用的条件，它不管on中的条件是否为真，都会返回左边表中的记录。</p>
<p>where条件是在临时表生成好后，再对临时表进行过滤的条件。这时已经没有left join的含义（必须返回左边表的记录）了，条件不为真的就全部过滤掉。</p>
<h4 id="数据库的操作"><a href="#数据库的操作" class="headerlink" title="数据库的操作"></a>数据库的操作</h4><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">DROP</span> DATABASE 数据库名称; <span class="comment">--删除数据库：</span></span><br><span class="line"><span class="keyword">DROP</span> <span class="keyword">TABLE</span> 表名称; <span class="comment">--删除表（表的结构、属性以及索引也会被删除）</span></span><br><span class="line"><span class="keyword">TRUNCATE</span> <span class="keyword">TABLE</span> 表名称; <span class="comment">--除去表内的数据，但并不删除表本身</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">ALTER</span> <span class="keyword">TABLE</span> table_name <span class="keyword">ADD</span> column_name datatype;<span class="comment">--添加列</span></span><br><span class="line"><span class="keyword">ALTER</span> <span class="keyword">TABLE</span> table_name <span class="keyword">DROP</span> <span class="keyword">COLUMN</span> column_name;<span class="comment">--删除列</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">VIEW</span> view_name <span class="keyword">AS</span></span><br><span class="line"><span class="keyword">SELECT</span> column_name(s)</span><br><span class="line"><span class="keyword">FROM</span> table_name</span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">condition</span></span><br></pre></td></tr></table></figure>

<h3 id="JDBC密码验证"><a href="#JDBC密码验证" class="headerlink" title="JDBC密码验证"></a>JDBC密码验证</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">verifyPassword</span><span class="params">(String username, String password)</span> </span>&#123;</span><br><span class="line">    Connection con = getConnection(); <span class="comment">// 方法是个已有的方法可以获取到数据库连接</span></span><br><span class="line">    String sql = <span class="string">&quot;SELECT password FROM users WHERE user_name=?&quot;</span>;</span><br><span class="line">    PreparedStatement pst = <span class="keyword">null</span>;</span><br><span class="line">    ResultSet rs = <span class="keyword">null</span>;</span><br><span class="line">    <span class="keyword">boolean</span> flag = <span class="keyword">false</span>;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        pst = con.prepareStatement(sql);</span><br><span class="line">        pst.setObject(<span class="number">1</span>, username);</span><br><span class="line">        rs = pst.executeQuery();</span><br><span class="line">        <span class="keyword">while</span> (rs.next()) &#123;</span><br><span class="line">            <span class="keyword">if</span> (rs.getString(<span class="string">&quot;password&quot;</span>).equals(password)) &#123;</span><br><span class="line">                flag = <span class="keyword">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (ClassNotFoundException e) &#123;</span><br><span class="line">        e.printStackTrace();</span><br><span class="line">    &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">        e.printStackTrace();</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> (rs != <span class="keyword">null</span>) rs.close();</span><br><span class="line">            <span class="keyword">if</span> (pst != <span class="keyword">null</span>) pst.close();</span><br><span class="line">            <span class="keyword">if</span> (con != <span class="keyword">null</span>) con.close();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (SQLException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> flag;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="备份与恢复"><a href="#备份与恢复" class="headerlink" title="备份与恢复"></a>备份与恢复</h3><p>要备份的目录下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysqldump -uroot -p dbname &gt; dbname.sql</span><br></pre></td></tr></table></figure>

<p>恢复：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysql -uroot -p dbname &lt; dbname.sql</span><br></pre></td></tr></table></figure>

<h3 id="索引"><a href="#索引" class="headerlink" title="索引"></a>索引</h3><p>Mysql建立索引（为了检索排序快的数据结构，增删改相应变慢）</p>
<h4 id="分类"><a href="#分类" class="headerlink" title="分类"></a>分类</h4><ul>
<li><p>主键索引（建表时自动创建）</p>
<p>innodb为<strong>聚簇索引</strong>，底层B+树（相较B树只在叶子结点存数据，且<strong>自动排序</strong>），根节点常驻内存</p>
<p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210313154029.png" alt="image-20210313154029281"></p>
</li>
<li><p>单值索引/普通索引</p>
<p>一个索引只包含一列，可以有多个单值索引（如id index，name index）</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 建表前添加索引，索引名默认列名</span></span><br><span class="line">creatr <span class="keyword">table</span> t_user(</span><br><span class="line">    id <span class="type">varchar</span>(<span class="number">20</span>) <span class="keyword">primary</span> key,</span><br><span class="line">    name <span class="type">varchar</span>(<span class="number">20</span>),</span><br><span class="line">    key (name)</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 建表后添加索引</span></span><br><span class="line"><span class="keyword">CREATE</span> INDEX 索引名 <span class="keyword">ON</span> 表名 (字段);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 删除索引</span></span><br><span class="line"><span class="keyword">drop</span> index 索引名 <span class="keyword">on</span> 表名</span><br></pre></td></tr></table></figure></li>
<li><p>唯一索引</p>
<p>索引值唯一，但允许一个为null（对比主键索引不能为空）</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 建表前添加索引，对比单值索引key</span></span><br><span class="line">creatr <span class="keyword">table</span> t_user(</span><br><span class="line">    id <span class="type">varchar</span>(<span class="number">20</span>) <span class="keyword">primary</span> key,</span><br><span class="line">    name <span class="type">varchar</span>(<span class="number">20</span>),</span><br><span class="line">    <span class="keyword">unique</span> (name)</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 建表后添加索引</span></span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">unique</span> INDEX 索引名 <span class="keyword">ON</span> 表名 (字段);</span><br></pre></td></tr></table></figure></li>
<li><p>复合索引</p>
<p>一个索引包含多个列，如（id，name）index，用在where id and name</p>
<p>原则：</p>
<ul>
<li>最左前缀原则，如abc，需为a、ab、abc</li>
<li>mysql会自动调整字段查询顺序以利用索引，如ba、acb、bac、cab、bca、cba</li>
</ul>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 建表前添加索引，对比单值索引key</span></span><br><span class="line">creatr <span class="keyword">table</span> t_user(</span><br><span class="line">    id <span class="type">varchar</span>(<span class="number">20</span>) <span class="keyword">primary</span> key,</span><br><span class="line">    name <span class="type">varchar</span>(<span class="number">20</span>),</span><br><span class="line">    age <span class="type">int</span>,</span><br><span class="line">    key (name,age)</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 建表后添加索引</span></span><br><span class="line"><span class="keyword">CREATE</span> INDEX 索引名 <span class="keyword">ON</span> 表名 (字段<span class="number">1</span>，字段<span class="number">2</span>);</span><br></pre></td></tr></table></figure></li>
</ul>
<h4 id="聚簇索引和非聚簇索引"><a href="#聚簇索引和非聚簇索引" class="headerlink" title="聚簇索引和非聚簇索引"></a>聚簇索引和非聚簇索引</h4><p>聚簇索引将数据和索引放在一起；非聚簇分开存储。</p>
<p>辅助索引是在聚簇索引之上建立的索引，<strong>非聚簇索引都是辅助索引</strong>。</p>
<p>辅助键索引叶子结点存放主键，不存放地址的原因是防止增删改导致地址变化。</p>
<p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210313155746.png" alt="image-20210313155746264"></p>
<p>非聚簇索引<strong>指向地址</strong>，单次查询效率高于聚簇索引。但是聚簇索引一次查询会将一页存入内存，下次访问同一页的数据就不必再访问磁盘，且在增删改时便于维护。</p>
<p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210313203941.png" alt="image-20210313203934463"></p>
<h4 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景"></a>使用场景</h4><ol>
<li>需要建立：<ul>
<li>主键</li>
<li>常做查询条件的字段</li>
<li>外键关联</li>
<li>查询排序字段</li>
<li>统计分组字段</li>
</ul>
</li>
<li>不要建立：<ul>
<li>表记录少</li>
<li>经常修改的字段</li>
<li>where用不上的字段</li>
<li>过滤性差的字段（性别等）</li>
</ul>
</li>
</ol>
<h3 id="一些题目"><a href="#一些题目" class="headerlink" title="一些题目"></a>一些题目</h3><p>一张表，里面有 ID 自增主键，当 insert 了 17 条记录之后，删除了第 15,16,17 条记录， 再把 Mysql 重启，再 insert 一条记录，这条记录的 ID 是 18 还是 15 ？</p>
<ul>
<li>如果表的类型是 MyISAM，那么是 18 因为 MyISAM 表会把自增主键的最大 ID 记录到数据文件里，重启 MySQL 自增主键的最大 ID 也不会丢失</li>
<li>如果表的类型是 InnoDB，那么是 15 InnoDB 表只是把自增主键的最大 ID 记录到内存中，所以重启数据库或者是对表进行 OPTIMIZE 操作，都会导致最大 ID 丢失</li>
</ul>
<hr>
<p>CHAR 列长度固定为创建表时声明的长度，长度值范围是 1 到 255。当 CHAR 值被存储时，它们被用<strong>空格</strong>填充到特定长度，检索 CHAR 值时需删除尾随空格</p>
<h2 id="Redis"><a href="#Redis" class="headerlink" title="Redis"></a>Redis</h2><h3 id="数据类型："><a href="#数据类型：" class="headerlink" title="数据类型："></a>数据类型：</h3><ol>
<li>String：key-value，最大512MB。SET\GET</li>
<li>Hash：key-value集合，适合存储对象。HMSET、HGET。存储用户信息，Hset(key,field,value)，如Hset(userKey,id,10)，通过Hget(userKey,id)获得</li>
<li>List：有序链表(底层是双向链表)，rpush、lpush、lrange key start stop，用于最新消息排行，模拟消息队列（如电商秒杀）</li>
<li>Set：String的无序集合。sadd k v、smembers k，用于自动排重，求好友列表交集</li>
<li>Zset有序集合：String的有序集合。zadd k score v，用于条件排序（商品综合、价格排序）</li>
<li>HyperLogLog基数</li>
</ol>
<h3 id="事务"><a href="#事务" class="headerlink" title="事务"></a>事务</h3><p>MULTI -&gt; 命令 -&gt; EXEC</p>
<p>单条命令原子性，事务非原子性。</p>
<ul>
<li><p>命令格式错误，直接回滚</p>
</li>
<li><p>命令格式正确，操作数据引发错误继续执行后续命令</p>
</li>
</ul>
<p>watch -&gt; 执行事务 -&gt; 回滚与否都unwatch</p>
<h3 id="持久化"><a href="#持久化" class="headerlink" title="持久化"></a>持久化</h3><ul>
<li>RDB：单独创建fork进程进行持久化，指定时间间隔将内存的数据集快照写入磁盘<br><img src="https://i.imgur.com/CFQj3Ov.png" alt="RDB"></li>
<li>AOF：以日志的形式记录操作，只许追加<br><img src="https://i.imgur.com/ku158eo.png" alt="AOF"></li>
</ul>
<h3 id="雪崩、缓存穿透、缓存击穿"><a href="#雪崩、缓存穿透、缓存击穿" class="headerlink" title="雪崩、缓存穿透、缓存击穿"></a>雪崩、缓存穿透、缓存击穿</h3><ul>
<li>雪崩：双十一<strong>大量ke</strong>y在Redis同时<strong>缓存时间到</strong>，同时过期，大量访问同时发送给数据库<ul>
<li>解决办法：设置不同key值的过期时间不同，如随机值，或者直接永不失效……</li>
</ul>
</li>
<li>缓存穿透（穿透攻击）：黑客故意发送一直不存在的id（如负数），Redis中<strong>没有</strong>，就不断向数据库发送请求<ul>
<li>解决办法：<strong>布隆过滤器</strong>、请求参数检查、限制IP访问等</li>
</ul>
</li>
<li>缓存击穿（击穿热点）：秒杀商品<strong>缓存时间到</strong>，对<strong>该key</strong>的大量访问发给数据库<ul>
<li>解决办法是在Redis和数据库之间用<strong>分布式锁</strong>，如单线程访问数据库，拿到数据后写回Redis，其他请求就可以重新从Redis拿数据了</li>
</ul>
</li>
</ul>
<h3 id="布隆过滤器"><a href="#布隆过滤器" class="headerlink" title="布隆过滤器"></a>布隆过滤器</h3><p>布隆过滤器用在前端和Redis之间，相当于白名单、黑名单，主要用于<strong>防止缓存穿透</strong>。布隆过滤器包含了数据库的数据，前端数据首先通过布隆过滤器，再发给Redis，有则返回数据；无则发给数据库，有则写回Redis并返回，无则返回空（布隆过滤器误判了）</p>
<h4 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h4><p>将一个值经过多个Hash函数得到不同的值存入数组对应位置中，a[Hash(“string”)] = 1。</p>
<p>优点：</p>
<ul>
<li>一个存放一个二进制位的数组，占用空间小</li>
<li>插入和查询速度快</li>
</ul>
<p>缺点</p>
<ul>
<li>不便于删除值。（有可能不同的值经过hash得到相同的值）</li>
<li>误判 </li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RedissonBloomFilter</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> RedissonClient redisson = <span class="keyword">null</span>;</span><br><span class="line">    <span class="keyword">static</span> RBloomFilter&lt;String&gt; bloomFilter = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        Config config = <span class="keyword">new</span> Config();</span><br><span class="line">        config.useSingleServer().setAddress(<span class="string">&quot;redis://192.168.245.130:6379&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//构造Redisson</span></span><br><span class="line">        redisson = Redisson.create(config);</span><br><span class="line"></span><br><span class="line">        bloomFilter = redisson.getBloomFilter(<span class="string">&quot;userIdFilter&quot;</span>);</span><br><span class="line">        initData(redisson, bloomFilter);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">initData</span><span class="params">(RedissonClient redisson, RBloomFilter&lt;String&gt; bloomFilter)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//初始化布隆过滤器：预计元素为100000000L,误差率为1%</span></span><br><span class="line">        bloomFilter.tryInit(<span class="number">100000000L</span>, <span class="number">0.01</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//将id为1和2插入到布隆过滤器中（只有id为1和2的放行）</span></span><br><span class="line">        bloomFilter.add(<span class="string">&quot;1&quot;</span>);</span><br><span class="line">        bloomFilter.add(<span class="string">&quot;2&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//只将id为1对应的user数据插入redis，访问2则需访问数据库</span></span><br><span class="line">        redisson.getBucket(<span class="string">&quot;1&quot;</span>).set(<span class="string">&quot;&#123;id:1, userName:&#x27;张三&#x27;, age:18&#125;&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 模拟缓存穿透</span></span><br><span class="line">        User user = getUserById(<span class="number">2L</span>);</span><br><span class="line">        System.out.println(<span class="string">&quot;user对象为：&quot;</span> + JSON.toJSONString(user));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> User <span class="title">getUserById</span><span class="params">(Long id)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">null</span> == id)</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        String idKey = id.toString();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 开始模拟缓存穿透</span></span><br><span class="line">        <span class="comment">// 前端查询key</span></span><br><span class="line">        <span class="keyword">if</span> (bloomFilter.contains(idKey)) &#123;</span><br><span class="line">            <span class="comment">// 通过过滤器白名单，去Redis查询</span></span><br><span class="line">            RBucket&lt;Object&gt; bucket = redisson.getBucket(idKey);</span><br><span class="line">            Object object = bucket.get();</span><br><span class="line"></span><br><span class="line">            <span class="comment">// redis查到了，直接返回</span></span><br><span class="line">            <span class="keyword">if</span> (<span class="keyword">null</span> != object) &#123;</span><br><span class="line">                System.out.println(<span class="string">&quot;从redis拿到了数据&quot;</span>);</span><br><span class="line">                String userStr = object.toString();</span><br><span class="line">                <span class="keyword">return</span> JSON.parseObject(userStr, User.class);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">// redis查不到，去查数据库</span></span><br><span class="line">            System.out.println(<span class="string">&quot;访问数据库了&quot;</span>);</span><br><span class="line">            User user = selectByDb(idKey);</span><br><span class="line">            <span class="keyword">if</span> (<span class="keyword">null</span> == user)</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">            <span class="keyword">else</span></span><br><span class="line">                redisson.getBucket(idKey).set(user.toString());</span><br><span class="line">            <span class="keyword">return</span> user;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;布隆过滤器拦截了&quot;</span>);</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 模拟连接数据库，此处要啥数据都有</span></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> User <span class="title">selectByDb</span><span class="params">(String idKey)</span> </span>&#123;</span><br><span class="line">        User user = <span class="keyword">new</span> User(Long.parseLong(idKey), <span class="string">&quot;张三&quot;</span>, <span class="number">18</span>);</span><br><span class="line">        <span class="keyword">return</span> user;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="redis在高并发下的使用案例"><a href="#redis在高并发下的使用案例" class="headerlink" title="redis在高并发下的使用案例"></a>redis在高并发下的使用案例</h3><p>如下为不断优化后的结果</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RedisController</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    StringRedisTemplate stringRedisTemplate;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping(&quot;/deduct&quot;)</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">deductStock</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        String lockKey = <span class="string">&quot;product_101&quot;</span>;</span><br><span class="line">        <span class="comment">//模拟唯一的client</span></span><br><span class="line">        String clientId = UUID.randomUUID().toString();</span><br><span class="line"></span><br><span class="line">        <span class="comment">//防止过程中抛异常，而最终无论如何都要释放锁</span></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">// 加锁的同时设置加锁者和过期时间</span></span><br><span class="line">            Boolean result = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, clientId, <span class="number">30</span>, TimeUnit.SECONDS);</span><br><span class="line">            <span class="keyword">if</span> (!result)</span><br><span class="line">                <span class="keyword">return</span> <span class="string">&quot;error_code&quot;</span>;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">int</span> stock = Integer.parseInt(stringRedisTemplate.opsForValue().get(<span class="string">&quot;stock&quot;</span>));</span><br><span class="line">            <span class="keyword">if</span> (stock &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                <span class="keyword">int</span> realStock = stock - <span class="number">1</span>;</span><br><span class="line">                stringRedisTemplate.opsForValue().set(<span class="string">&quot;stock&quot;</span>, realStock + <span class="string">&quot;&quot;</span>);</span><br><span class="line">                System.out.println(<span class="string">&quot;扣减成功，剩余库存：&quot;</span> + realStock);</span><br><span class="line">            &#125; <span class="keyword">else</span></span><br><span class="line">                System.out.println(<span class="string">&quot;扣减失败，库存不足&quot;</span>);</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            <span class="comment">// 确定是谁加的锁，才能释放锁</span></span><br><span class="line">            <span class="keyword">if</span> (clientId.equals(stringRedisTemplate.opsForValue().get(lockKey)))</span><br><span class="line">                stringRedisTemplate.delete(lockKey);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;end&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>但是在失效时间和finally的if处仍有问题，于是使用Redisson解决</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RedisController</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    StringRedisTemplate stringRedisTemplate;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    Redisson redisson;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping(&quot;/deduct&quot;)</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">deductStock</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        String lockKey = <span class="string">&quot;product_101&quot;</span>;</span><br><span class="line"></span><br><span class="line">        RLock redissonLock = redisson.getLock(lockKey);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            redissonLock.lock();</span><br><span class="line"></span><br><span class="line">            <span class="keyword">int</span> stock = Integer.parseInt(stringRedisTemplate.opsForValue().get(<span class="string">&quot;stock&quot;</span>));</span><br><span class="line">            <span class="keyword">if</span> (stock &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                <span class="keyword">int</span> realStock = stock - <span class="number">1</span>;</span><br><span class="line">                stringRedisTemplate.opsForValue().set(<span class="string">&quot;stock&quot;</span>, realStock + <span class="string">&quot;&quot;</span>);</span><br><span class="line">                System.out.println(<span class="string">&quot;扣减成功，剩余库存：&quot;</span> + realStock);</span><br><span class="line">            &#125; <span class="keyword">else</span></span><br><span class="line">                System.out.println(<span class="string">&quot;扣减失败，库存不足&quot;</span>);</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            redissonLock.unlock();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;end&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>redisson底层使用的lua脚本在redis当成一条原子性指令执行，上述代码问题在于主从节点的同步问题</p>
<h3 id="实现分布式锁zookeeper和redis对比"><a href="#实现分布式锁zookeeper和redis对比" class="headerlink" title="实现分布式锁zookeeper和redis对比"></a>实现分布式锁zookeeper和redis对比</h3><ul>
<li>在CAP即一致性（Consistency）、可用性（Availability）、分区容错性（Partition tolerance）上：<ul>
<li>zookeeper侧重CP，加锁后先同步给从节点至主+从占半数以上，再返回；如果主节点宕机后选取已同步的从节点作主节点</li>
<li>redis侧重AP，线程访问redis，加锁后立刻返回，性能较高</li>
</ul>
</li>
</ul>
<p>分布式锁还可以用于数据库和缓存双写一致性问题</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://yuzhenxin.gitee.io/2020/10/15/Java%E5%9F%BA%E7%A1%80/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="余振鑫">
      <meta itemprop="description" content="余振鑫的个人博客">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="余振鑫的Hexo博客">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2020/10/15/Java%E5%9F%BA%E7%A1%80/" class="post-title-link" itemprop="url">Java基础</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-10-15 00:00:00" itemprop="dateCreated datePublished" datetime="2020-10-15T00:00:00+08:00">2020-10-15</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2022-01-18 23:07:20" itemprop="dateModified" datetime="2022-01-18T23:07:20+08:00">2022-01-18</time>
              </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="Java基础"><a href="#Java基础" class="headerlink" title="Java基础"></a>Java基础</h1><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p>JAVA_HOME: D:\Programming\Java\jdk1.8.0_281</p>
<p>CLASSPATH: .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;</p>
<p>Path: %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin</p>
<h2 id="JDK、JRE和JVM"><a href="#JDK、JRE和JVM" class="headerlink" title="JDK、JRE和JVM"></a>JDK、JRE和JVM</h2><p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210314220455.png" alt="image-20210314220448618"></p>
<h2 id="JVM"><a href="#JVM" class="headerlink" title="JVM"></a>JVM</h2><h3 id="JVM的内存结构"><a href="#JVM的内存结构" class="headerlink" title="JVM的内存结构"></a>JVM的内存结构</h3><p><img src="https://i.imgur.com/ZKBo8pD.png"></p>
<img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307223301.png" alt="image-20210223221957681" style="zoom:50%;" />

<img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307223325.png" alt="image-20210223221715303" style="zoom:50%;" />

<ul>
<li><strong>堆内存</strong>：保存的是对象的具体信息，在程序之中堆内存空间的开辟是通过new完成的（<strong>gc发生地</strong>），该区域是被线程共享的</li>
<li><strong>栈内存</strong>：栈的结构是<strong>栈帧</strong>组成的，调用一个方法就压入一帧，帧上面存储<strong>局部变量表</strong>、操作数栈、方法出口等信息，局部变量表存放的是 <strong>8 大基础类型</strong>加上一个应用类型，所以还是一个指向<strong>堆内存的地址（对象的引用）</strong>，即：通过地址找到堆内存，而后找到对象内容（<strong>基本数据类型在此分配</strong>）</li>
<li><strong>方法区</strong>：主要是存储类信息，常量池（static 常量和 static 变量），编译后的代码（字节码）等数据，该区域是被线程共享的</li>
<li>本地方法栈：主要为 Native 方法服务</li>
<li>程序计数器：记录当前线程执行的行号</li>
</ul>
<h3 id="JVM垃圾回收机制"><a href="#JVM垃圾回收机制" class="headerlink" title="JVM垃圾回收机制"></a>JVM垃圾回收机制</h3><p>没有任何栈内存所指向的堆内存空间为<strong>垃圾空间</strong>，将被GC定期回收</p>
<ul>
<li><p>回收机制</p>
<p>在 Java 中，程序员是不需要显示的去释放一个对象的内存的，而是由虚拟机自行执行。在 JVM 中，有一个垃圾回收线程，它是低优先级的，在正常情况下是不会执行的，只有在<strong>虚拟机空闲或者当前堆内存不足</strong>时，才会触发执行，扫面那些没有被任何引用的对象，并将 它们添加到要回收的集合中，进行回收。</p>
</li>
<li><p>地点：发生在堆(heap)里</p>
</li>
<li><p>分类：</p>
<ol>
<li>收集频繁的Young区</li>
<li>较少收集的Old区</li>
<li>基本不动Perm区</li>
</ol>
</li>
<li><p>GC判定算法</p>
<ul>
<li><p>引用计数法（被淘汰，不能解决相互引用的问题）</p>
</li>
<li><p>可达性分析：从GCRoot开始向下搜索形成引用链，当一个对象没有与任何引用链相连，则不可用，应回收（不是一次判断就回收，首先判断对象是否覆盖finalize()，<strong>未覆盖则回收</strong>；若覆盖未执行，则放入F-Queue，执行finalize()，执行后再判断对象是否可达，可达则复活，不可达就回收）（finalize()代价高，一般不覆盖）</p>
<p>GCRoot对象有：栈中引用的对象，方法区中类静态属性引用的对象，方法区中常量引用的对象，本地方法栈（Native方法）引用对象</p>
</li>
</ul>
</li>
<li><p>GC收集方法</p>
<ol>
<li><p>复制算法：年轻代使用Minor GC。将可用内存按容量划分为相等的两部分，然后每次只使用其中的一块，当一块内存用完时，就将还存活的对象复制到第二块内存上，然后一次性清楚完第一块内存，再将第二块上的对象复制到第一块</p>
<ul>
<li>优点：没有标记清除，效率高；没有内存碎片</li>
<li>缺点：需要双倍空间</li>
<li>改进：每次都会优先使用 Eden 区，若 Eden 区满，就将对象复制到第二块内存区上，然后清除 Eden 区，如果此时存活的对象太多，以至于 Survivor 不够时，会将这些对象通过分配担保机制复制到老年代中。</li>
</ul>
</li>
<li><p>标记清除：老年代使用Full GC</p>
<ul>
<li>优点：无需额外空间</li>
<li>缺点：两次扫描，耗时严重；会产生内存碎片</li>
</ul>
</li>
<li><p>标记压缩：老年代使用Full GC</p>
<ul>
<li>优点：没有内存碎片</li>
<li>缺点：需要移动对象的成本</li>
</ul>
</li>
<li><p>标记清除压缩：上述两种结合</p>
<ul>
<li>优点：减少移动对象成本</li>
</ul>
</li>
</ol>
</li>
</ul>
<h3 id="堆的分区"><a href="#堆的分区" class="headerlink" title="堆的分区"></a>堆的分区</h3><p>分类：</p>
<ul>
<li>新生代（8：1：1）<ul>
<li>Eden区（8）</li>
<li>Survivor区（1+1）<ul>
<li>from区</li>
<li>to区</li>
</ul>
</li>
</ul>
</li>
<li>老生代</li>
</ul>
<h2 id="类加载器"><a href="#类加载器" class="headerlink" title="类加载器"></a>类加载器</h2><ol>
<li>BootstrapClassLoader是ExtClassLoader的父类加载器（非继承，属性parent），加载%JAVA_HOME%\lib下的jar包和class文件</li>
<li>ExtClassLoader是AppClassLoader的父类加载器，加载%JAVA_HOME%\lib\ext下的jar包和class文件</li>
<li>AppClassLoader是系统类加载器，加载classpath下的类文件，通常继承它实现自定义类加载器</li>
</ol>
<h3 id="双亲委托模型"><a href="#双亲委托模型" class="headerlink" title="双亲委托模型"></a>双亲委托模型</h3><p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210316161128.png" alt="image-20210316161128315"></p>
<p>好处：</p>
<ul>
<li>安全性，避免用户写的类替换Java核心类，如String（自己写的无效）</li>
<li>避免类的重复加载，JVM区分不同类依靠<strong>类名和类加载器</strong></li>
</ul>
<h2 id="String"><a href="#String" class="headerlink" title="String"></a>String</h2><h3 id="String、StringBuilder、StringBuffer的比较"><a href="#String、StringBuilder、StringBuffer的比较" class="headerlink" title="String、StringBuilder、StringBuffer的比较"></a>String、StringBuilder、StringBuffer的比较</h3><ul>
<li>操作数量较少的字符串用String，不可修改的字符串；</li>
<li>在单线程且操作大量字符串用StringBuilder，速度快，但线程不安全，可修改；</li>
<li>在多线程且操作大量字符串用StringBuffer，<strong>线程安全</strong>（每个方法加了synchronized），可修改。</li>
</ul>
<p>String不可修改，如下则会创建多个垃圾空间，不可取！</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">String str = <span class="string">&quot;www.&quot;</span>;</span><br><span class="line">str += <span class="string">&quot;mldn.&quot;</span>;</span><br><span class="line">str = str+<span class="string">&quot;cn&quot;</span>;</span><br><span class="line">System.out.println(str);</span><br></pre></td></tr></table></figure>

<img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307223405.png" alt="image-20210223221847696" style="zoom: 50%;" />

<h3 id="字符串常量池"><a href="#字符串常量池" class="headerlink" title="字符串常量池"></a>字符串常量池</h3><p>String的intern()方法：HotSpot VM里，记录interned string的一个全局表叫做StringTable，它本质上就是个HashSet。注意它只存储对java.lang.String实例的引用，而不存储String对象的内容。</p>
<p><strong>字符串常量池只存储引用，不存储内容！</strong></p>
<ul>
<li>如果常量池中存在当前字符串，那么直接返回常量池中它的引用。</li>
<li>如果常量池中没有此字符串, 会将此字符串引用保存到常量池中后, 再直接返回该字符串的引用！</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyTest</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">test1</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 字符串常量池的StringTable表指向&quot;1&quot;，栈的s1指向new String(&quot;1&quot;)</span></span><br><span class="line">        String s1 = <span class="keyword">new</span> String(<span class="string">&quot;1&quot;</span>);</span><br><span class="line">        <span class="comment">// 字符串常量池已指向&quot;1&quot;，返回指向&quot;1&quot;的引用，但s1没有接收此新的引用</span></span><br><span class="line">        s1.intern();</span><br><span class="line">        <span class="comment">// 字符串常量池已指向&quot;1&quot;，返回指向&quot;1&quot;的引用给s2</span></span><br><span class="line">        String s2 = <span class="string">&quot;1&quot;</span>;</span><br><span class="line">        System.out.println(s1 == s2); <span class="comment">// false</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 堆中开辟两个new String(&quot;1&quot;)和一个new String(&quot;11&quot;)，s3指向后者</span></span><br><span class="line">        String s3 = <span class="keyword">new</span> String(<span class="string">&quot;1&quot;</span>) + <span class="keyword">new</span> String(<span class="string">&quot;1&quot;</span>);</span><br><span class="line">        <span class="comment">// 字符串常量池没有指向&quot;11&quot;，于是增加指向new String(&quot;11&quot;)，并返回此引用，但s3没有接受此相同的引用</span></span><br><span class="line">        s3.intern();</span><br><span class="line">        <span class="comment">// 字符串常量池指向new String(&quot;11&quot;)，返回该引用给s4</span></span><br><span class="line">        String s4 = <span class="string">&quot;11&quot;</span>;</span><br><span class="line">        System.out.println(s3 == s4); <span class="comment">// true</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">test2</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        String s1 = <span class="keyword">new</span> String(<span class="string">&quot;1&quot;</span>);</span><br><span class="line">        String s2 = <span class="string">&quot;1&quot;</span>;</span><br><span class="line">        s1.intern();</span><br><span class="line">        System.out.println(s1 == s2); <span class="comment">// false</span></span><br><span class="line"></span><br><span class="line">        String s3 = <span class="keyword">new</span> String(<span class="string">&quot;1&quot;</span>) + <span class="keyword">new</span> String(<span class="string">&quot;1&quot;</span>);</span><br><span class="line">        <span class="comment">// 字符串常量池不存在&quot;11&quot;，在堆中开辟&quot;11&quot;并指向它，返回此引用给s4</span></span><br><span class="line">        String s4 = <span class="string">&quot;11&quot;</span>;</span><br><span class="line">        s3.intern();</span><br><span class="line"><span class="comment">//       s3 = s3.intern(); //此行执行，结果就是true</span></span><br><span class="line">        System.out.println(s3 == s4); <span class="comment">// false</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// s1 == s3 == s4 !=s2</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">test3</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 堆中开辟5个空间，s1指new String(&quot;hello&quot;)</span></span><br><span class="line">        String s1 = <span class="keyword">new</span> String(<span class="string">&quot;he&quot;</span>) + <span class="keyword">new</span> String(<span class="string">&quot;llo&quot;</span>);</span><br><span class="line">        <span class="comment">// 堆中开辟5个空间，s2指new String(&quot;hello&quot;)，但s1!=s2</span></span><br><span class="line">        String s2 = <span class="keyword">new</span> String(<span class="string">&quot;h&quot;</span>) + <span class="keyword">new</span> String(<span class="string">&quot;ello&quot;</span>);</span><br><span class="line">        <span class="comment">// 字符串常量池指向s1的指向，引用赋给s3</span></span><br><span class="line">        String s3 = s1.intern();</span><br><span class="line">        <span class="comment">// 字符串常量池的指向赋给s4</span></span><br><span class="line">        String s4 = s2.intern();</span><br><span class="line">        System.out.println(s1 == s3); <span class="comment">// true</span></span><br><span class="line">        System.out.println(s1 == s4); <span class="comment">// true</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        test1();</span><br><span class="line">        test2();</span><br><span class="line">        test3();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="和equals-比较"><a href="#和equals-比较" class="headerlink" title="==和equals()比较"></a>==和equals()比较</h3><ul>
<li>“==”对比的是<strong>栈中的值</strong>。基本类型直接在栈中分配，引用类型是堆中内存对象的地址</li>
<li>equals()<ul>
<li>在Object类中默认采用==，通常会重写</li>
<li>String类重写后直接进行字符串内容的判断，区分大小写</li>
</ul>
</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//直接赋值过程中，自动保存在堆中的常量池，如果有相同数据定义时可以减少对象的产生</span></span><br><span class="line">String strA = <span class="string">&quot;mldn&quot;</span>;</span><br><span class="line">String strB = <span class="string">&quot;mldn&quot;</span>;</span><br><span class="line">System.out.println(strA==strB);<span class="comment">//true</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//构造方法，会产生两个实例化对象，并且不会自动入池，无法实现对象的重用，但是可以利用intern()方法手工入池处理。</span></span><br><span class="line">String strC = <span class="keyword">new</span> String(<span class="string">&quot;mldn&quot;</span>);</span><br><span class="line">System.out.println(strA==strB);<span class="comment">//false</span></span><br></pre></td></tr></table></figure>

<p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307223434.png" alt="image-20210223222041289"></p>
<p>System.out.println()默认使用toString方法</p>
<h3 id="equals-和hashCode"><a href="#equals-和hashCode" class="headerlink" title="equals()和hashCode()"></a>equals()和hashCode()</h3><p>hashCode()方法和equals()方法都是用来对比两个对象是否相等一致。</p>
<p>因为重写的equals()里一般比较的比较全面比较复杂，这样效率就比较低，而利用hashCode()进行对比，则只要生成一个hash值进行比较就可以了，<strong>效率很高</strong>。</p>
<p>但是hashCode()<strong>并不是完全可靠</strong>，有时候不同的对象他们生成的hashcode也会一样（生成hash值得公式可能存在的问题），所以hashCode()只能说是大部分时候可靠，并不是绝对可靠，即：</p>
<ol>
<li><p>equals()相等的两个对象他们的hashCode()肯定相等，也就是用equals()对比是绝对可靠的。</p>
</li>
<li><p>hashCode()相等的两个对象他们的equals()不一定相等，也就是hashCode()不是绝对可靠的。</p>
</li>
</ol>
<p>所有对于需要大量并且快速的对比的话如果都用equals()去做显然效率太低，所以解决方式是，每当需要对比的时候，<strong>首先用hashCode()去对比</strong>，如果hashCode()不一样，则表示这两个对象肯定不相等（也就是不必再用equals()去再对比了），**如果hashCode()相同，此时再对比他们的equals()**，如果equals()也相同，则表示这两个对象是真的相同了，这样既能大大提高了效率也保证了对比的绝对正确性！</p>
<h5 id="为什么重写equals-一定要重写hashCode"><a href="#为什么重写equals-一定要重写hashCode" class="headerlink" title="为什么重写equals()一定要重写hashCode()"></a>为什么重写equals()一定要重写hashCode()</h5><p>hashCode()默认<strong>返回内存地址</strong>使得不同对象永不相等（equals()默认为==，对比引用类型时也是<strong>返回地址</strong>），为了保证equals()相等时hashCode()一定相等，**重写equals()一定要重写hashCode()**！</p>
<h3 id="正则表达式"><a href="#正则表达式" class="headerlink" title="正则表达式"></a>正则表达式</h3><p>^表示匹配输入的开始，$表示匹配输入的结束，?表示匹配某元素0次或1次</p>
<p>[a-zA-Z\d] 表示匹配一个大小写字母或者数字，\d匹配数字，\w 表示匹配字母数字或下划线， \D 表示匹配一个非数字字符，{m,n}表示最少匹配m次，最多匹配n次。</p>
<p>+表示匹配某元素1次或多次，*表示匹配某元素0次或多次，.可以匹配除了换行符\n \r外的任何单个字符</p>
<h2 id="final关键字"><a href="#final关键字" class="headerlink" title="final关键字"></a>final关键字</h2><ul>
<li>修饰类：类不可被继承</li>
<li>修饰方法：方法不可被重写但可重载</li>
<li>修饰变量：变量被赋值后不能更改<ul>
<li>修饰成员变量：在<strong>声明</strong>时或者<strong>非静态初始化块</strong>或者<strong>构造器</strong>中赋值</li>
<li>修饰类变量：在<strong>声明</strong>时或者<strong>静态初始化块</strong>中赋值</li>
<li>修饰局部变量：在<strong>使用前</strong>赋值即可</li>
<li>修饰基本数据类型：赋值后不能更改</li>
<li>修饰引用型变量：初始化后不能<strong>指向其他对象</strong>，但是<strong>引用的值</strong>可变</li>
</ul>
</li>
</ul>
<h3 id="方法内部类和匿名内部类只能访问局部final变量"><a href="#方法内部类和匿名内部类只能访问局部final变量" class="headerlink" title="方法内部类和匿名内部类只能访问局部final变量"></a>方法内部类和匿名内部类只能访问局部final变量</h3><p>因为内部类和外部类是同一级别的，内部类<strong>不会因为外部类方法执行完毕而销毁</strong>。</p>
<p>当内部类调用外部类方法的局部变量（下图的x）时，为了防止方法结束导致x销毁进而内部类无法使用x，JVM会<strong>复制</strong>一份<strong>局部变量</strong>x到<strong>内部类的成员变量</strong>中。</p>
<p>为了保持局部变量和内部类成员变量的<strong>一致性</strong>，使用final让x无法修改。（是一种妥协）</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">OutClass</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">outPrint</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">final</span> <span class="keyword">int</span> x = <span class="number">10</span>;</span><br><span class="line">        <span class="class"><span class="keyword">class</span> <span class="title">InnerClass</span></span>&#123;</span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">inPrint</span><span class="params">()</span></span>&#123;</span><br><span class="line">                System.out.println(x);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">new</span> InnerClass().inPrint();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="面向对象"><a href="#面向对象" class="headerlink" title="面向对象"></a>面向对象</h2><p>三大特性：<strong>封装、继承、多态</strong></p>
<h3 id="多态"><a href="#多态" class="headerlink" title="多态"></a>多态</h3><ul>
<li>编译多态：方法重载（overload）</li>
<li>运行多态：方法重写（override）</li>
</ul>
<h3 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h3><p><strong>子类重写父类成员方法，只要没有super声明，一律使用子类的。</strong></p>
<p>如*Father a = new Son();*a在方法里调用其他重写方法时默认用到**this.**method()，这个this就代表当前对象，是Son，所以使用子类的</p>
<h4 id="对象转型"><a href="#对象转型" class="headerlink" title="对象转型"></a>对象转型</h4><ul>
<li><p>上转型：向上转型一定是安全的，但是一旦向上转型为父类对象，就不能调用子类原本特有的方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Son extends Father</span></span><br><span class="line">Father fs = <span class="keyword">new</span> Son();</span><br><span class="line">fs.I_am_a_human(); <span class="comment">//调用儿子的重写方法，我是儿子，不是父亲</span></span><br><span class="line">fs.I_am_a_student(); <span class="comment">//编译错误，此方法儿子独有</span></span><br></pre></td></tr></table></figure></li>
<li><p>下转型：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Father fs = <span class="keyword">new</span> Son();</span><br><span class="line"><span class="keyword">if</span>(fs <span class="keyword">instanceof</span> Son)&#123;<span class="comment">//可以使用instanceof关键字判断</span></span><br><span class="line">    Son son = (Son)fs;<span class="comment">//向下转型，容易出错，其实就是转回去了</span></span><br><span class="line">    son.I_am_a_student();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="重载和重写"><a href="#重载和重写" class="headerlink" title="重载和重写"></a>重载和重写</h3><ul>
<li>重载：方法名相同，参数（类型/个数/顺序）不同，返回值和修饰符<strong>可以</strong>不同</li>
<li>重写：方法名参数相同。返回值和抛出异常范围≤父类，访问修饰符≥父类（private方法不能重写）</li>
</ul>
<h2 id="基本类型和包装类"><a href="#基本类型和包装类" class="headerlink" title="基本类型和包装类"></a>基本类型和包装类</h2><h3 id="比较"><a href="#比较" class="headerlink" title="比较"></a>比较</h3><ul>
<li><p>Integer==int会将Integer自动拆箱<strong>比较数值</strong></p>
</li>
<li><p>Integer==Integer，在**[-128,127]<strong>为true（直接引用常量池中的 Integer 对象），否则为false。</strong>除非显示声明new对象**</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Integer a1 = <span class="number">1</span>;</span><br><span class="line">Integer b1 = <span class="number">1</span>;</span><br><span class="line">System.out.println(a1==b1); <span class="comment">//true</span></span><br><span class="line"></span><br><span class="line">Integer a2 = <span class="keyword">new</span> Integer(<span class="number">1</span>);</span><br><span class="line">Integer b2 = <span class="keyword">new</span> Integer(<span class="number">1</span>);</span><br><span class="line">System.out.println(a2==b2);  <span class="comment">// false</span></span><br></pre></td></tr></table></figure></li>
<li><p>Integer.equals(Integer)，首先<strong>比较类型</strong>，再比较值，都相等才为true</p>
</li>
<li><p>Integer.equals(int)，会将int<strong>自动装箱</strong>，再按上一条规则对比</p>
</li>
</ul>
<h3 id="类型转换"><a href="#类型转换" class="headerlink" title="类型转换"></a>类型转换</h3><ol>
<li>通过包装类Integer.toString(123)将整型转换为字符串；</li>
<li>通过Integer.parseInt(str)将字符串转换为int类型；</li>
<li>通过Integer.valueOf(str)把字符串转换为包装类然后通过自动拆箱。</li>
</ol>
<p>int类型可以自动装箱转为Integer，也可以向上转型为double，但不能直接转为Double！</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">double</span> a = <span class="number">1</span>;</span><br><span class="line"><span class="comment">//Double b = 1; 编译错误</span></span><br></pre></td></tr></table></figure>

<h3 id="不同类型的算术运算"><a href="#不同类型的算术运算" class="headerlink" title="不同类型的算术运算"></a>不同类型的算术运算</h3><p>只要两个操作数中有一个是double/float/long类型的，另一个将会被转换成double/float/long类型，并且结果也是double/float/long类型，否则操作数为：byte、short、int 、char，两个数都会被转换成int类型，并且结果也是int类型。<strong>若被声明final 类型不会转换！</strong></p>
<h3 id="BigDecimal"><a href="#BigDecimal" class="headerlink" title="BigDecimal"></a>BigDecimal</h3><p>题目：将一堆String类型的数字累加</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">sum</span><span class="params">(ArrayList&lt;String&gt; numbers)</span> </span>&#123;</span><br><span class="line">    BigDecimal result = <span class="keyword">new</span> BigDecimal(<span class="string">&quot;0&quot;</span>);</span><br><span class="line">    <span class="keyword">for</span> (String str : numbers) &#123;</span><br><span class="line">        BigDecimal bd1 = <span class="keyword">new</span> BigDecimal(str);</span><br><span class="line">        result = result.add(bd1);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> result.toString();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="接口和抽象类"><a href="#接口和抽象类" class="headerlink" title="接口和抽象类"></a>接口和抽象类</h2><p>接口字段默认：public static final</p>
<p>接口方法默认：public abstract</p>
<p>接口方法的修饰符可以是：<strong>public，abstract</strong>，default，static（后两者需要有{}）</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">A</span></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> a = <span class="number">1</span>;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">abstract</span> String <span class="title">a</span><span class="params">()</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">default</span> String <span class="title">b</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">static</span> String <span class="title">c</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>抽象类可以有普通成员方法，抽象类只能单继承，接口可以多实现</p>
<h3 id="比较-1"><a href="#比较-1" class="headerlink" title="比较"></a>比较</h3><p>抽象类表达is的关系，奥迪 is a Car，Car包含并实现子类<strong>通用特性</strong>，如run()，其他差异化特性由子类实现，如换挡()</p>
<p>接口表达like的关系，Birds like an aircraft，核心是<strong>定义行为</strong>，不关心具体实现过程。</p>
<h2 id="枚举"><a href="#枚举" class="headerlink" title="枚举"></a>枚举</h2><p>枚举项都是本类的实例，不能用new创建对象，在类外只能使用类名.枚举项</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">enum</span> <span class="title">Direction</span> </span>&#123;</span><br><span class="line">    FRONT, BEHIND, LEFT, RIGHT(<span class="string">&quot;红色&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line">Direction d = Direction.FRONT;</span><br></pre></td></tr></table></figure>

<h3 id="enum与Enum的区别"><a href="#enum与Enum的区别" class="headerlink" title="enum与Enum的区别"></a>enum与Enum的区别</h3><ul>
<li>enum：是从JDK1.5之后提供的一个关键字，用于定义枚举类。</li>
<li>Enum：是一个抽象类，所以使用enum定义的类就默认继承了此类。</li>
</ul>
<h2 id="异常"><a href="#异常" class="headerlink" title="异常"></a>异常</h2><p>Throwable是顶级父类，有Exception和Error子类</p>
<p>try catch只会匹配一个异常处理catch，所以一般范围小的异常放前面。</p>
<h3 id="throw和throws的区别"><a href="#throw和throws的区别" class="headerlink" title="throw和throws的区别"></a>throw和throws的区别</h3><ul>
<li>throw：是在代码块中使用的，主要是手工进行异常对象的抛出；</li>
<li>throws：是在方法定义上使用的，表示将此方法中可能产生的异常明确告诉给调用处，由调用处进行处理。</li>
<li>throws表示出现异常的一种可能性，并不一定会发生这些异常；throw则是抛出了异常，执行throw则一定抛出了某种异常。</li>
</ul>
<p>使用throws关键字来进行异常类型的标注，必须有对应的try.catch处理</p>
<h3 id="try-catch-返回值"><a href="#try-catch-返回值" class="headerlink" title="try{}catch{}返回值"></a>try{}catch{}返回值</h3><p><strong>结论：finally一定会执行，try和finally都有return的话返回finally的；try有return而finally无return则finally修改值无效（catch和finally类似）</strong></p>
<p>属于return之前执行finally</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">test</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> i = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> i;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">        i = <span class="number">10</span>;</span><br><span class="line">        <span class="keyword">return</span> i;</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        i = <span class="number">20</span>;</span><br><span class="line">        <span class="keyword">return</span> i;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>返回20</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">test</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> i = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> i;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">        i = <span class="number">10</span>;</span><br><span class="line">        <span class="keyword">return</span> i;</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        i = <span class="number">20</span>;</span><br><span class="line"><span class="comment">//        return i;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>返回0</p>
<h2 id="内部类"><a href="#内部类" class="headerlink" title="内部类"></a>内部类</h2><p>静态内部类只能访问外围类的<strong>全部静态</strong>属性；普通内部类可以访问外围类的<strong>全部属性</strong></p>
<p>构造方法可以用private，protected，default，private</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Outer</span> </span>&#123;  <span class="comment">//外部类</span></span><br><span class="line">    <span class="keyword">private</span> String msg = <span class="string">&quot;www.mldn.cm&quot;</span>;  <span class="comment">//私有成员属性</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">fun</span><span class="params">()</span> </span>&#123; <span class="comment">//普通方法</span></span><br><span class="line">        Inner in  = <span class="keyword">new</span> Inner();  <span class="comment">//实例化内部类对象</span></span><br><span class="line">        in.print();  <span class="comment">//调用内部类方法</span></span><br><span class="line">        System.out.println(in.info); <span class="comment">//访问内部类的私有属性</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Inner</span> </span>&#123;  <span class="comment">//在Outer类的内部定义了Inner类</span></span><br><span class="line">        <span class="keyword">private</span> String info = <span class="string">&quot;今天天气不好，收衣服拉！&quot;</span>;</span><br><span class="line">        <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">print</span><span class="params">()</span></span>&#123; <span class="comment">//此方法只有在外部类能调用</span></span><br><span class="line">            System.out.println(Outer.<span class="keyword">this</span>.msg);  <span class="comment">//Outer里类中的属性</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Outer out = <span class="keyword">new</span> Outer();  <span class="comment">//实例化外部类对象</span></span><br><span class="line">out.fun();  <span class="comment">//调用外部类中的方法</span></span><br><span class="line"></span><br><span class="line">Outer.Inner in = <span class="keyword">new</span> Outer().<span class="function">new <span class="title">Inner</span><span class="params">()</span></span>;</span><br><span class="line"><span class="comment">//in.print();  //此方法无法执行，private</span></span><br></pre></td></tr></table></figure>

<h3 id="静态内部类"><a href="#静态内部类" class="headerlink" title="静态内部类"></a>静态内部类</h3><p>在内部类上使用了static定义，那么这个内部类就变为了“外部类”，就相当于是一个独立的程序类</p>
<p><strong>static定义的不管是类还是方法只能够访问static成员，所以static定义的内部类只能访问外部类中的static属性和方法。</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Outer</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> String MSG = <span class="string">&quot;www.mldn.cn&quot;</span>;</span><br><span class="line">    <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">Inner</span> </span>&#123;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">print</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            System.out.println(Outer.MSG);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Outer.Inner in = <span class="keyword">new</span> Outer.Inner();</span><br><span class="line">in.print();</span><br></pre></td></tr></table></figure>

<h3 id="方法内部类"><a href="#方法内部类" class="headerlink" title="方法内部类"></a>方法内部类</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Outer</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String msg = <span class="string">&quot;www.mldn.cn&quot;</span> ;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">fun</span><span class="params">(<span class="keyword">long</span> time)</span> </span>&#123;</span><br><span class="line">        <span class="class"><span class="keyword">class</span> <span class="title">Inner</span> </span>&#123; <span class="comment">//内部类</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">print</span><span class="params">()</span> </span>&#123;</span><br><span class="line">                System.out.println(Outer.<span class="keyword">this</span>.msg);</span><br><span class="line">                System.out.println(time);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">new</span> Inner().print(); <span class="comment">//方法中直接实例化内部类对象</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JavaDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String args[])</span> </span>&#123;</span><br><span class="line">        <span class="keyword">new</span> Outer().fun(<span class="number">23943342L</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="匿名内部类"><a href="#匿名内部类" class="headerlink" title="匿名内部类"></a>匿名内部类</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">IMessage</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">send</span><span class="params">(String str)</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JavaDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String args[])</span> </span>&#123;</span><br><span class="line">        IMessage msg = <span class="keyword">new</span> IMessage() &#123;  <span class="comment">//匿名内部类</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">send</span><span class="params">(String str)</span> </span>&#123;</span><br><span class="line">                System.out.println(str);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        msg.send(<span class="string">&quot;www.mldn.cn&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="集合"><a href="#集合" class="headerlink" title="集合"></a>集合</h2><p><strong>Collection</strong> 接口的接口 对象的集合（单列集合）<br>├——-<strong>List</strong> 接口：元素按进入先后有序保存，可重复<br>│—————-├ <strong>LinkedList</strong> 接口实现类，链表，插入删除，没有同步，线程不安全<br>│—————-├ <strong>ArrayList</strong> 接口实现类，数组，随机访问，没有同步，线程不安全<br>│—————-└ <strong>Vector</strong> 接口实现类 数组，同步，线程安全<br>│ ———————-└ <strong>Stack</strong> 是Vector类的实现类<br>└——-<strong>Set</strong> 接口： 仅接收一次，不可重复，并做内部排序<br>├—————-└<strong>HashSet</strong> 数组+链表+红黑树，使用hash表（数组）存储元素<br>│————————└ <strong>LinkedHashSet</strong> 链表维护元素的插入次序<br>└ —————-<strong>TreeSet</strong> 底层实现为红黑树，元素排好序</p>
<p><strong>Map</strong> 接口 键值对的集合 （双列集合）<br>├———<strong>Hashtable</strong> 数组+链表+红黑树，接口实现类， 同步， 线程安全<br>├———<strong>HashMap</strong> 数组+链表+红黑树，接口实现类 ，没有同步， 线程不安全<br>│—————–├ <strong>LinkedHashMap</strong> 双向链表和哈希表实现<br>│—————–└ <strong>WeakHashMap</strong><br>├ ——–<strong>TreeMap</strong> 红黑树(自平衡排序二叉树)对所有的key进行排序，没有同步， 线程不安全<br>└———<strong>IdentifyHashMap</strong></p>
<h3 id="Comparable和Comparator"><a href="#Comparable和Comparator" class="headerlink" title="Comparable和Comparator"></a>Comparable和Comparator</h3><p>用于定义Arrays.sort()时的规则</p>
<ul>
<li><p>Comparable：在<strong>Entity</strong>上实现Comparable接口，里面只有一个compareTo()的方法。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Person</span> <span class="keyword">implements</span> <span class="title">Comparable</span>&lt;<span class="title">Person</span>&gt; </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> age;</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compareTo</span><span class="params">(Person per)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>.age - per.age; <span class="comment">//升序</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Person data[] = <span class="keyword">new</span> Person[]&#123;</span><br><span class="line">        <span class="keyword">new</span> Person(<span class="string">&quot;小强A&quot;</span>, <span class="number">80</span>),</span><br><span class="line">        <span class="keyword">new</span> Person(<span class="string">&quot;小强B&quot;</span>, <span class="number">100</span>),</span><br><span class="line">        <span class="keyword">new</span> Person(<span class="string">&quot;小强C&quot;</span>, <span class="number">50</span>)&#125;;</span><br><span class="line">Arrays.sort(data);</span><br><span class="line">System.out.println(Arrays.toString(data));</span><br></pre></td></tr></table></figure></li>
<li><p>Comparator：在Arrays.sort()中传递<strong>实现Comparator接口的对象</strong>，里面有compare()方法。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">PersonCompatator</span> <span class="keyword">implements</span> <span class="title">Comparator</span>&lt;<span class="title">Person</span>&gt;</span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compare</span><span class="params">(Person p1, Person p2)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> p1.getAge()-p2.getAge();<span class="comment">//升序</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Person data[] = <span class="keyword">new</span> Person[]&#123;</span><br><span class="line">        <span class="keyword">new</span> Person(<span class="string">&quot;小强A&quot;</span>, <span class="number">80</span>),</span><br><span class="line">        <span class="keyword">new</span> Person(<span class="string">&quot;小强B&quot;</span>, <span class="number">100</span>),</span><br><span class="line">        <span class="keyword">new</span> Person(<span class="string">&quot;小强C&quot;</span>, <span class="number">50</span>)&#125;;</span><br><span class="line">Arrays.sort(data, <span class="keyword">new</span> PersonCompatator());</span><br><span class="line">System.out.println(Arrays.toString(data));</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="List"><a href="#List" class="headerlink" title="List"></a>List</h3><ol>
<li>ArrayList：底层数据结构是<strong>动态数组</strong>，查询快，增删慢，线程不安全，效率高，可以存储重复元素。在指定初始容量且使用尾插法的情况下，性能甚至超过LinkedList<ul>
<li>扩容：长度超过数组长度（初始化为0插入数据时变成10，超过10就1.5倍）会新建数组，并将数据复制过去</li>
</ul>
</li>
<li>LinkedList 底层数据结构是<strong>双向链表</strong>，查询慢，增删快，线程不安全，效率高，可以存储重复元素。遍历的时候必须用iterator（for循环get(i)为下标访问，性能消耗极大）</li>
<li>Vector: 底层数据结构是<strong>数组</strong>，查询快，增删慢，<strong>线程安全</strong>，效率低，可以存储重复元素</li>
</ol>
<h3 id="Set"><a href="#Set" class="headerlink" title="Set"></a>Set</h3><p>实现唯一性的过程：只有<strong>hashCode()<strong>（先执行）和</strong>equals()<strong>（前者相等才执行）都</strong>相等</strong>才<strong>不存储</strong>。</p>
<h4 id="HashSet"><a href="#HashSet" class="headerlink" title="HashSet"></a>HashSet</h4><p>底层数据结构采用<strong>哈希表</strong>实现，元素<strong>无序且唯一</strong>，线程不安全，效率高，可以存储null元素。</p>
<p>采用哈希算法，底层用数组存储数据。默认初始化容量16，加载因子0.75</p>
<h4 id="TreeSet"><a href="#TreeSet" class="headerlink" title="TreeSet"></a>TreeSet</h4><p>底层数据结构采用<strong>红黑树</strong>来实现，元素<strong>唯一且已经排好序</strong>。</p>
<p>二叉树结构保证了元素的<strong>有序性</strong>。重写<strong>Comparable</strong>接口里面的compareTo()方法来进行排序。</p>
<h3 id="Map"><a href="#Map" class="headerlink" title="Map"></a>Map</h3><h4 id="HashMap"><a href="#HashMap" class="headerlink" title="HashMap"></a>HashMap</h4><p>HashMap的数据结构：数组+链表+红黑树，当链表的值大于8的时候，就会转成红黑树存储。</p>
<p>HashMap默认初始容量16，加载因子0.75，当存储容量大于16*0.75的时候，扩容两倍，并将原数据复制到新的数组上。</p>
<p>HashMap有个静态内部类Entry，该类包含键、值、哈希值和链表的next指向。遍历是无序的，LinkHashMap是其子类，可以使遍历有序。</p>
<p>key为null存在下标为0的位置</p>
<h5 id="元素存储"><a href="#元素存储" class="headerlink" title="元素存储"></a>元素存储</h5><p>两次hash()再模length得到数组下标。<strong>hash%length==hash&amp;(length-1</strong>)的前提是 <strong>length 是 2 的 n 次⽅</strong></p>
<p>插入数据时若位置为空，直接插入。否则判断equals()，相同则覆盖，不同则形成链表。</p>
<p>链表高度达到8</p>
<ul>
<li>数组长度小于64，数组扩容</li>
<li>数组长度长度达到64，链表转化成红黑树，长度低于6将红黑树变回链表</li>
</ul>
<h5 id="线程不安全"><a href="#线程不安全" class="headerlink" title="线程不安全"></a>线程不安全</h5><ul>
<li>假设AB的数据都定位到数组同一个下标，线程A发现元素为空，正准备插入，然后CPU让给线程B，线程B发现也为空，插入数据，然后回到A，A直接覆盖数据导致B插入的数据丢失</li>
<li>扩容</li>
</ul>
<h5 id="扩容"><a href="#扩容" class="headerlink" title="扩容"></a>扩容</h5><p>数组中元素的个数达到负载因子（0.75）*数组长度，扩容2倍。</p>
<p>复制一份数组，迁移数据（重新计算hash()并取模）。</p>
<ul>
<li>对于链表上的数据迁移，1.7为头插法，链表顺序会反过来（尾变成头）。</li>
<li>线程不安全，线程1发现要扩容，A.next = B，A迁移后要迁移B，然后此时阻塞。线程2也发现要扩容，把B迁移过去后，B.next = A，此时A恢复，要继续迁移B，发现已迁移，继续迁移B的下一个，但此时B.next = A，形成闭链，死锁。</li>
<li>故1.8采用尾插法</li>
</ul>
<h5 id="Java7"><a href="#Java7" class="headerlink" title="Java7"></a>Java7</h5><p>数组+链表（头插法，易导致死循环）</p>
<p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307223509.png" alt="image-20210130202021553"></p>
<h5 id="Java8"><a href="#Java8" class="headerlink" title="Java8"></a>Java8</h5><p>数组+链表（尾插法）+红黑树</p>
<p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307223528.png" alt="image-20210130202047812"></p>
<p>Java8在链表超过8个元素时将链表转换成红黑树，降低时间复杂度至O(logN)</p>
<h4 id="ConcurrentHashMap"><a href="#ConcurrentHashMap" class="headerlink" title="ConcurrentHashMap"></a>ConcurrentHashMap</h4><h5 id="Java7-1"><a href="#Java7-1" class="headerlink" title="Java7"></a>Java7</h5><p>使用ReentrantLock+Segment[]（内部类）+HashEntry[]</p>
<img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307223547.png" alt="image-20210201101846915" style="zoom:50%;" />

<p>由于HashMap线程不安全，使用ConcurrentHashMap，<strong>分段锁</strong>。是一个Segment数组，线程只能轮流访问同一个Segment，每个Segment相当于一个HashMap，有一个HashEntry[]，保存key、value和指向下一个节点的指针。</p>
<p>默认分为16个段，即锁的<strong>并发度</strong>，可以减少锁粒度提升并发性</p>
<h6 id="元素查询"><a href="#元素查询" class="headerlink" title="元素查询"></a>元素查询</h6><p>第一次hash定位到Segment，第二次定位到元素所在链表的头部</p>
<p>put：（2次hash）</p>
<ol>
<li> <strong>计算hash</strong>，<strong>定位到segment</strong>，segment如果是空就先初始化</li>
<li> 使用ReentrantLock加锁，如果获取锁失败则尝试自旋，自旋超过次数就阻塞获取，保证一定获取锁成功</li>
<li> 遍历HashEntry，就是和HashMap一样（<strong>计算hash</strong>，定位到数组中的位置），数组中key和hash一样就直接替换，不存在就再插入链表，链表同样</li>
</ol>
<h5 id="Java8-1"><a href="#Java8-1" class="headerlink" title="Java8"></a>Java8</h5><p>Synchronized+CAS+Node+红黑树</p>
<p>查找替换赋值都用CAS</p>
<h6 id="锁链表的头节点"><a href="#锁链表的头节点" class="headerlink" title="锁链表的头节点"></a>锁链表的头节点</h6><ul>
<li>数组其他元素读写不受影响，锁粒度更细</li>
<li>扩容阻塞所有<strong>写</strong>操作</li>
</ul>
<h6 id="读操作无锁"><a href="#读操作无锁" class="headerlink" title="读操作无锁"></a>读操作无锁</h6><p>Node的val和next使用volatile修饰，保证可见性</p>
<p>数组用volatile修饰，保证扩容可见</p>
<p>put：</p>
<ol>
<li>首先计算hash，遍历node数组，如果node是空的话，就通过CAS+自旋的方式初始化</li>
<li>如果当前数组位置是空则直接通过<strong>CAS自旋写入数据</strong></li>
<li>如果hash==MOVED，说明需要扩容，执行扩容</li>
<li>如果都不满足，就使用synchronized写入数据，写入数据同样判断链表、红黑树，链表写入和HashMap的方式一样，key hash一样就覆盖，反之就尾插法，链表长度超过8就转换成红黑树</li>
</ol>
<p>get:无锁，使用volatile</p>
<h4 id="HashMap和Hashtable区别"><a href="#HashMap和Hashtable区别" class="headerlink" title="HashMap和Hashtable区别"></a>HashMap和Hashtable区别</h4><ul>
<li><p>HashMap是线程不安全的，性能高；HashTable线程安全，性能低</p>
</li>
<li><p>HashMap用迭代器遍历索引从小到大，初始容量16，扩容是容量*2；HashTable用迭代器遍历索引从大到小，初始容量11，扩容是容量*2 +1；</p>
</li>
<li><p>HashMap允许key和value为null，Hashtable不允许</p>
</li>
</ul>
<h2 id="多线程"><a href="#多线程" class="headerlink" title="多线程"></a>多线程</h2><h3 id="进程间的通信IPC"><a href="#进程间的通信IPC" class="headerlink" title="进程间的通信IPC"></a>进程间的通信IPC</h3><ol>
<li>管道(Pipe)：<strong>半双工</strong>的通信方式，管道可用于<strong>具有亲缘关系</strong>进程间的通信，允许一个进程和另一个与它有共同祖先的进程之间进行通信。</li>
<li>命名管道(named pipe)：命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还<strong>允许无亲缘</strong>关系进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令 mkfifo 或系统调用 mkfifo 来创建。</li>
<li>信号(Signal)：信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进 程间通信外,进程还可以发送信号给进程本身;linux 除了支持 Unix 早期信号语义函数 sigal 外,还支持语义符合 Posix.1 标准的信号函数 sigaction(实际上,该函数是基于 BSD 的,BSD 为了实现可靠信号机制,又能够统一对外接口,用 sigaction 函数重新实现了 signal 函数)。</li>
<li>消息(Message)队列：消息队列是消息的链接表，包括 Posix 消息队列 system V 消息队 列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消 息。消息队列<strong>克服了信号承载信息量少</strong>、<strong>管道只能承载无格式字节流</strong>以及缓冲区大小受限等</li>
<li>共享内存：使得多个进程可以访问同一块内存空间,是<strong>最快的</strong>可用 IPC 形式。是针对其他通信机制运行效率较低而设计的。往往<strong>与其它通信机制如信号量结合使用</strong>，来达到进程间的同步及互斥。 </li>
<li>信号量(semaphore)：基于操作系统的 PV 操作，是一个计数器，常作为<strong>锁机制</strong>，作为<strong>进程间以及同一进程不同线程之间</strong>的<strong>同步</strong>手段。</li>
<li>套接字(Socket)：更为一般的进程间通信机制,可用于<strong>不同机器之间</strong>的进程间通信。起初是由 Unix 系统的 BSD 分支开发出来的，但现在一般可以移植到其它类 Unix 系统上:Linux 和 System V 的变种都支持套接字。</li>
</ol>
<h3 id="线程创建"><a href="#线程创建" class="headerlink" title="线程创建"></a>线程创建</h3><p>Java创建线程的两种方式，启动线程的唯一方法就是通过 **Thread 类的 start()**实例方法。start()方法是一个 native 方法，它将启动一个新线程，并执行 run()方法。</p>
<p><em>直接调用run()起不了多线程，就是普通方法</em></p>
<ol>
<li><p>继承 Thread 类。Thread 类本质上是实现了 Runnable 接口的一个实例。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyThread</span> <span class="keyword">extends</span> <span class="title">Thread</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;MyThread.run()&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">MyThread myThread1 = <span class="keyword">new</span> MyThread();</span><br><span class="line">myThread1.start();</span><br></pre></td></tr></table></figure></li>
<li><p>实现 Runnable 接口，此处使用<strong>代理设计模式</strong>，Thread为代理类。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyThread</span> <span class="keyword">extends</span> <span class="title">OtherClass</span> <span class="keyword">implements</span> <span class="title">Runnable</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;MyThread.run()&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//启动 MyThread 需要首先实例化一个 Thread，并传入自己的 MyThread 实例</span></span><br><span class="line">MyThread myThread = <span class="keyword">new</span> MyThread();</span><br><span class="line">Thread thread = <span class="keyword">new</span> Thread(myThread);</span><br><span class="line"><span class="comment">//Thread 的 run()方法就会调用target.run()</span></span><br><span class="line">thread.start(); </span><br></pre></td></tr></table></figure></li>
<li><p>Callable接口：实现Runnable接口的线程执行完毕后无法获取一个返回值，所以从JDK1.5之后就提出了一个新的接口：java.util.concurrent.Callable接口。Callable定义的时候可以设置一个<strong>泛型</strong>，此泛型的类型就是<strong>返回数据</strong>的类型。Callable还可以<strong>声明抛出异常</strong>。</p>
<p>由于Callable对象不能直接作为Thread的target，可以使用Future接口的实现类<strong>FutureTask</strong>（也实现了Runnable接口）<strong>包装Callable对象</strong>作为target</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyThread</span> <span class="keyword">implements</span> <span class="title">Callable</span>&lt;<span class="title">String</span>&gt;</span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">call</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;线程执行&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RunnableDemo</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception</span>&#123;</span><br><span class="line">        FutureTask&lt;String&gt; task = <span class="keyword">new</span> FutureTask&lt;String&gt;(<span class="keyword">new</span> MyThread());</span><br><span class="line">        <span class="keyword">new</span> Thread(task).start();</span><br><span class="line">        System.out.println(<span class="string">&quot;线程返回数据&quot;</span>+task.get());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ol>
<h3 id="线程基本方法"><a href="#线程基本方法" class="headerlink" title="线程基本方法"></a>线程基本方法</h3><p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307223615.png" alt="image-20210131114149829"></p>
<ul>
<li>start()启动线程–&gt;进入就绪态–&gt;运行run()–&gt;运行态</li>
<li>sleep()是Thread类的方法，调用时线程<strong>不释放锁</strong></li>
<li>wait()是Object类的方法，调用时<strong>释放锁</strong>，进入<strong>等待锁定池</strong>，使用notify()后本线程才进入<strong>对象锁定池</strong>准备获取对象锁进入运行状态。方法一般用在同步方法或同步代码块中</li>
<li>yield()会使当前线程让出 CPU 执行时间片，与其他线程一起重新竞争 CPU 时间片</li>
<li>join() ，等待其他线程终止，在当前线程中调用一个线程的 join() 方法，则当前线程转为<strong>阻塞态</strong>，当另一个线程结束，原线程再由阻塞状态变为<strong>就绪态</strong>。方法一般用于主线程启动子线程，并<strong>需要子线程返回结果</strong>，即等待子线程结束后再继续</li>
<li>interrupt()，给这个线程一个通知信号，会影响这个线程内部的一个<strong>中断标识位</strong>，线程本身并<strong>不会改变状态</strong>。当调用sleep()后再调用interrupt()，会抛出 <strong>InterruptedException</strong>，从而使线程提前结束TIMED-WATING 状态。许多抛出该异常的方法在抛出异常前，都会<strong>清除中断标识位</strong>，调用 isInterrupted()方法将会返回 false，从而结束run()，线程结束</li>
<li>notify()，随机唤醒在此对象监视器上等待的一个线程</li>
</ul>
<h3 id="线程死锁的四个必要条件"><a href="#线程死锁的四个必要条件" class="headerlink" title="线程死锁的四个必要条件"></a>线程死锁的四个必要条件</h3><p><strong>1、互斥条件</strong></p>
<p>即一段时间内某资源仅为一个线程所占有，此时若其他线程请求该资源，则请求线程都需要等待。</p>
<p><strong>2、不可剥夺条件</strong></p>
<p>即线程所获得的资源在未使用完毕之前，不能被其他线程强行夺走，只能由获得该资源的线程自己主动释放。</p>
<p><strong>3、请求与保持条件</strong>（吃着碗里的望着锅里的）</p>
<p>即线程已经至少保持了一个资源，但又提出了新的资源请求，而该资源已经被其他线程占有，此时请求线程被阻塞，但对自己已获得的资源保持不放。</p>
<p><strong>4、循环等待条件</strong></p>
<p>存在一种线程资源的循环等待链，链中每一个已获得的资源同时被链中下一个线程所请求。</p>
<h3 id="线程池"><a href="#线程池" class="headerlink" title="线程池"></a>线程池</h3><h5 id="ThreadPoolExecutor"><a href="#ThreadPoolExecutor" class="headerlink" title="ThreadPoolExecutor"></a>ThreadPoolExecutor</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ThreadPoolExecutor(<span class="keyword">int</span> corePoolSize,<span class="keyword">int</span> maximumPoolSize,<span class="keyword">long</span> keepAliveTime,TimeUnit unit,BlockingQueue workQueue ,ThreadFactory threadFactory,RejectedExecutionHandler handler)</span><br></pre></td></tr></table></figure>

<ul>
<li>corePoolSize：线程池基本大小，没有任务执行时池子的大小</li>
<li>maximumPoolSize：线程最大大小，表示可同时活动的线程数量上限</li>
<li>keepAliveTime：线程最大空闲时间，线程空闲时间超过该值将标记为可回收</li>
<li>unit：线程最大空闲时间的时间单位</li>
<li>workQueue：线程队列，该队列满后线程池会创建超出 corePoolSize 大小的线程数量</li>
<li>threadFactory：线程创建工厂，在线程池需要创建一个线程时会用到</li>
<li>hander：拒绝策略，有 AbortPolicy，CallerRunsPolicy，DiscardPolicy，DiscardOldestPolicy</li>
</ul>
<p>任务交到线程池，判断<strong>核心线程数是否已满</strong>，如果未满则<strong>直接创建核心线程</strong>来处理该请求。如果有多于corePoolSize但小于maximumPoolSize线程正在运行，则仅当<strong>队列已满</strong>时才会创建新线程。如果maximumPoolSize达到最大值会执行拒绝策略。</p>
<p><img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307223644.png" alt="20210307143536"></p>
<h3 id="Java锁"><a href="#Java锁" class="headerlink" title="Java锁"></a>Java锁</h3><ol>
<li>乐观锁，在更新的时候会判断一下在此期间别人有没有去更新这个数据，采取在写时<strong>先读出当前版本号</strong>，然后加锁操作（比较跟上一次的版本号，如果一样则更新），如果失败则要重复读-比较-写的操作。 Java 中的乐观锁基本都是通过 <strong>CAS</strong> 操作实现的，CAS 是一种更新的原子操作，比较当前值跟传入值是否一样，一样则更新，否则失败。</li>
<li>悲观锁，每次在读写数据的时候都会上锁，Java中的悲观锁就是<strong>Synchronized</strong>。</li>
<li>自旋锁，如果持有锁的线程能在很短时间内释放锁资源，等待竞争锁的线程就不需要进入阻塞挂起状态，它们只需要<strong>等一等</strong>（自旋），等持有锁的线程释放锁后即可立即获取锁，这样就避免用户线程和内核的切换的消耗。如果持有锁的线程执行的时间超过自旋等待的最大时间扔没有释放锁，这时争用线程会停止自旋进入阻塞状态。（就是让 cup 在做无用功，锁的竞争不激烈时使用）</li>
<li>Semaphore 信号量，可以控制同时访问的线程个数，通过 acquire() 获取一个许可，如果没有就等待，而 release() 释放一个许可。</li>
<li>可重入锁，为了解决自己锁死自己的情况。如果这个对象没有锁定，或者当前线程已经拥有了这个对象的锁，把锁的计数器+1。可重入就是说某个线程已经获得某个锁，可以再次获取锁而不会出现死锁。</li>
</ol>
<h3 id="Synchronized"><a href="#Synchronized" class="headerlink" title="Synchronized"></a>Synchronized</h3><p>同步锁，可以把任意一个非 NULL 的对象当作锁。他属于独占式的<strong>悲观锁</strong>，同时属于<strong>可重入锁、非公平锁</strong>。<strong>保证可见性和原子性</strong></p>
<p>非公平锁的体现：非公平主要表现在获取锁的行为上，并非是按照申请锁的时间前后给等待线程分配锁的，每当锁被释放后，任何一个线程都有机会竞争到锁，这样做的目的是为了提高执行性能，缺点是可能会产生线程饥饿现象。</p>
<ul>
<li>作用范围：<ul>
<li>作用于方法时，锁住的是对象的实例(this)</li>
<li>当作用于静态方法时，锁住的是Class实例</li>
<li>synchronized 作用于一个对象实例时，锁住的是所有以该对象为锁的代码块</li>
</ul>
</li>
</ul>
<h3 id="ReentrantLock"><a href="#ReentrantLock" class="headerlink" title="ReentrantLock"></a>ReentrantLock</h3><p>ReentantLock 继承接口 Lock 并实现了接口中定义的方法，是一种<strong>可重入锁</strong>，除了能完成 synchronized 所能完成的所有工作外，还提供了诸如可响应中断锁、可轮询锁请求、定时锁等避免多线程死锁的方法。</p>
<h4 id="对比Synchronized"><a href="#对比Synchronized" class="headerlink" title="对比Synchronized"></a>对比Synchronized</h4><p>共同点：</p>
<ul>
<li>都是用来协调多线程对共享对象、变量的访问</li>
<li>都是可重入锁，同一线程可以多次获得同一个锁</li>
<li>都保证了可见性和互斥性</li>
</ul>
<p>不同点：</p>
<ul>
<li><p>ReentrantLock 通过方法 lock()与 unlock()来进行加锁与解锁操作，与 synchronized 会 被 JVM 自动解锁机制不同，ReentrantLock 加锁后需要手动进行解锁。为了避免程序出现异常而无法正常解锁的情况，使用 ReentrantLock 必须在 finally 控制块中进行解锁操作。</p>
</li>
<li><p>ReentrantLock 相比 synchronized 的优势是可中断、<strong>公平锁</strong>、多个锁。这种情况下需要使用ReentrantLock。</p>
</li>
</ul>
<h3 id="volatile关键字"><a href="#volatile关键字" class="headerlink" title="volatile关键字"></a>volatile关键字</h3><p><strong>保证可见性</strong></p>
<p>轻量级同步机制，适合这种场景：一个变量被多个线程共享，线程直接给这个变量赋值。</p>
<img src="https://gitee.com/yuzhenxin/images/raw/master/img/20210307223721.png" alt="image-20210131121958166" style="zoom:50%;" />

<p>如图是对一般变量的读写。而声明变量是 volatile 的话，JVM 保证了每次读变量都从<strong>内存</strong>中读，跳过 CPU cache 这一步。</p>
<ul>
<li>保证可见性：及时通知其他线程本线程对数据的修改</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.concurrent.TimeUnit;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyTest</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        MyData myData = <span class="keyword">new</span> MyData();</span><br><span class="line">        <span class="keyword">new</span> Thread(() -&gt; &#123;</span><br><span class="line">            System.out.println(Thread.currentThread().getName() + <span class="string">&quot;线程来了&quot;</span>);</span><br><span class="line">            <span class="comment">// 等待3秒</span></span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                TimeUnit.SECONDS.sleep(<span class="number">1</span>);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">            myData.change();</span><br><span class="line">            System.out.println(Thread.currentThread().getName() + <span class="string">&quot;更新数值为:&quot;</span> + myData.num);</span><br><span class="line">        &#125;, <span class="string">&quot;A&quot;</span>).start();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 线程修改后main线程才能获取值为10</span></span><br><span class="line">        <span class="keyword">while</span> (myData.num == <span class="number">0</span>) &#123;</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(Thread.currentThread().getName() + <span class="string">&quot;线程结束，主线程获取数值为:&quot;</span> + myData.num);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyData</span> </span>&#123;</span><br><span class="line">    <span class="keyword">volatile</span> <span class="keyword">int</span> num = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">change</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.num = <span class="number">10</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li><p>原子性</p>
<ul>
<li><p>**i++**不保证原子性，后续线程覆盖前面的值造成丢失写值</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyTest</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        MyData myData = <span class="keyword">new</span> MyData();</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">20</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">new</span> Thread(() -&gt; &#123;</span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; <span class="number">1000</span>; j++) &#123;</span><br><span class="line">                    myData.incrase();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;, String.valueOf(i)).start();</span><br><span class="line">            ;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 最后用main线程查看结果</span></span><br><span class="line">        <span class="keyword">while</span> (Thread.activeCount() &gt; <span class="number">2</span>) &#123; <span class="comment">// main线程和GC线程</span></span><br><span class="line">            <span class="comment">// 退让</span></span><br><span class="line">            Thread.yield();</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(Thread.currentThread().getName() + </span><br><span class="line">                <span class="string">&quot;\t finally num = &quot;</span> + myData.num); <span class="comment">// 基本不会是20000</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyData</span> </span>&#123;</span><br><span class="line">    <span class="keyword">volatile</span> <span class="keyword">int</span> num = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">incrase</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        num++;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>可使用AtomicInteger解决：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyData</span> </span>&#123;</span><br><span class="line">    AtomicInteger atomicInteger = <span class="keyword">new</span> AtomicInteger();</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">incrase</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        atomicInteger.getAndIncrement();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li><p>但是对变量的写操作<strong>不依赖于当前值</strong>（如单纯赋值），且该变量没有包含在具有其他变量的不变式中（状态<strong>真正独立于</strong>程序内其他内容）则<strong>可以保证原子性</strong></p>
</li>
</ul>
</li>
<li><p>禁止指令重排：多线程中线程交替执行，由于编译器优化重排（考虑数据依赖关系）的存在，线程间使用的变量未必保持一致性，因此禁止指令重排可避免</p>
</li>
</ul>
<p>内存模型（JMM）：描述规范，不真实存在。每个线程都有一个自己的工作空间（栈），对放在主内存（堆）的共享变量必须拷到自己的工作空间操作再写回主内存</p>
<h3 id="CAS"><a href="#CAS" class="headerlink" title="CAS"></a>CAS</h3><ul>
<li>比较：<ul>
<li>Synchronized悲观锁，保持一致性，并发性下降</li>
<li>CAS<strong>乐观锁</strong>，不加锁保持一致性</li>
</ul>
</li>
<li>简介：依赖Unsafe类，CAS使JVM发出汇编指令，能直接操作内存，不被打断，无线程安全问题。</li>
<li>原理：AtomicInteger的getAndIncrement()保证原子性，依赖Unsafe底层的CAS，判断工作<strong>内存的值</strong>是否为预期主内存的值，是则更新，否则重新获得再次比较 </li>
<li>缺点：<ol>
<li>循环时间长开销大（<strong>自旋</strong>）</li>
<li>只能保证<strong>一个共享变量</strong>的原子操作（方法参数当前对象只有一个）</li>
<li><strong>ABA问题</strong>：拷贝回内存后操作完成再比较有时间差，其他线程可在之前改动后再改回原值<br>解决：<strong>加版本号（时间戳）</strong>–AtomicStampedReference</li>
</ol>
</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.concurrent.TimeUnit;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.atomic.AtomicReference;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.atomic.AtomicStampedReference;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyTest</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> AtomicReference&lt;Integer&gt; atomicReference = <span class="keyword">new</span> AtomicReference&lt;Integer&gt;(<span class="number">100</span>);</span><br><span class="line">    <span class="keyword">static</span> AtomicStampedReference&lt;Integer&gt; atomicStampedReference = <span class="keyword">new</span> AtomicStampedReference&lt;Integer&gt;(<span class="number">100</span>, <span class="number">1</span>);</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// ABA问题</span></span><br><span class="line">        <span class="keyword">new</span> Thread(() -&gt; &#123;</span><br><span class="line">            atomicReference.compareAndSet(<span class="number">100</span>, <span class="number">101</span>);</span><br><span class="line">            atomicReference.compareAndSet(<span class="number">101</span>, <span class="number">100</span>);</span><br><span class="line">        &#125;, <span class="string">&quot;t1&quot;</span>).start();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">new</span> Thread(() -&gt; &#123;</span><br><span class="line">            <span class="comment">// 保证t1完成一次ABA</span></span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                TimeUnit.SECONDS.sleep(<span class="number">1</span>);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">            System.out.println(atomicReference.compareAndSet(<span class="number">100</span>, <span class="number">2019</span>) + <span class="string">&quot;\t&quot;</span> + atomicReference.get());</span><br><span class="line">        &#125;, <span class="string">&quot;t2&quot;</span>).start();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 等t1、t2结束</span></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            TimeUnit.SECONDS.sleep(<span class="number">2</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 解决ABA问题</span></span><br><span class="line">        <span class="keyword">new</span> Thread(() -&gt; &#123;</span><br><span class="line">            <span class="keyword">int</span> stamp = atomicStampedReference.getStamp();</span><br><span class="line">            System.out.println(Thread.currentThread().getName() + <span class="string">&quot;\t第1次版本号&quot;</span> + stamp);</span><br><span class="line">            <span class="comment">// 保证t1完成一次ABA</span></span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                TimeUnit.SECONDS.sleep(<span class="number">1</span>);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">            atomicStampedReference.compareAndSet(<span class="number">100</span>, <span class="number">101</span>, atomicStampedReference.getStamp(),</span><br><span class="line">                    atomicStampedReference.getStamp() + <span class="number">1</span>);</span><br><span class="line">            System.out.println(Thread.currentThread().getName() + <span class="string">&quot;\t第2次版本号&quot;</span> + atomicStampedReference.getStamp());</span><br><span class="line">            atomicStampedReference.compareAndSet(<span class="number">101</span>, <span class="number">100</span>, atomicStampedReference.getStamp(),</span><br><span class="line">                    atomicStampedReference.getStamp() + <span class="number">1</span>);</span><br><span class="line">            System.out.println(Thread.currentThread().getName() + <span class="string">&quot;\t第3次版本号&quot;</span> + atomicStampedReference.getStamp());</span><br><span class="line">        &#125;, <span class="string">&quot;t3&quot;</span>).start();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">new</span> Thread(() -&gt; &#123;</span><br><span class="line">            <span class="keyword">int</span> stamp = atomicStampedReference.getStamp();</span><br><span class="line">            System.out.println(Thread.currentThread().getName() + <span class="string">&quot;\t第1次版本号&quot;</span> + stamp);</span><br><span class="line">            <span class="comment">// 保证t3完成一次ABA</span></span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                TimeUnit.SECONDS.sleep(<span class="number">3</span>);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">            ;</span><br><span class="line">            System.out.println(<span class="string">&quot;t4是否修改成功：&quot;</span> + atomicStampedReference.compareAndSet(<span class="number">100</span>, <span class="number">2019</span>, stamp, stamp + <span class="number">1</span>) + <span class="string">&quot;\t&quot;</span></span><br><span class="line">                    + <span class="string">&quot;当前最新版本号：&quot;</span> + atomicStampedReference.getStamp());</span><br><span class="line">        &#125;, <span class="string">&quot;t4&quot;</span>).start();</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>输出：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">true    2019</span><br><span class="line">t3    第1次版本号1</span><br><span class="line">t4    第1次版本号1</span><br><span class="line">t3    第2次版本号2</span><br><span class="line">t3    第3次版本号3</span><br><span class="line">t4是否修改成功：false    当前最新版本号：3</span><br></pre></td></tr></table></figure>

<h3 id="ThreadLocal"><a href="#ThreadLocal" class="headerlink" title="ThreadLocal"></a>ThreadLocal</h3><p>ThreadLocal没有实现任何接口，用于线程间的数据隔离。它会为每个使用该变量的线程提供独立的变量副本，每个线程可以独立地改变自己的副本。</p>
<h3 id="BIO、NIO、AIO"><a href="#BIO、NIO、AIO" class="headerlink" title="BIO、NIO、AIO"></a>BIO、NIO、AIO</h3><p><strong>BIO</strong>：同步阻塞式IO，服务器实现模式为一个连接一个线程，即客户端有连接请求时服务器端就需要启动一个线程进行处理，如果这个连接不做任何事情会造成不必要的线程开销，当然可以通过线程池机制改善。 （<strong>Jedis</strong>）<br><strong>NIO</strong>：同步非阻塞式IO，服务器实现模式为一个请求一个线程，即客户端发送的连接请求都会注册到多路复用器上，多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。（<strong>lettuce</strong>)<br><strong>AIO</strong>：异步非阻塞式IO，服务器实现模式为一个有效请求一个线程，客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。 </p>
<h2 id="反射"><a href="#反射" class="headerlink" title="反射"></a>反射</h2><h3 id="获取反射对象的方法"><a href="#获取反射对象的方法" class="headerlink" title="获取反射对象的方法"></a>获取反射对象的方法</h3><ol>
<li><p>使用new 静态加载</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Person p=<span class="keyword">new</span> Person();</span><br><span class="line">Class clazz=p.getClass();</span><br></pre></td></tr></table></figure></li>
<li><p>调用某个类的 class 属性来获取该类对应的 Class 对象</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Class clazz=Person.class;</span><br></pre></td></tr></table></figure></li>
<li><p>调用 Class.forName() 方法（最安全/性能最好）</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Class clazz=Class.forName(<span class="string">&quot;类的全路径&quot;</span>);</span><br></pre></td></tr></table></figure></li>
</ol>
<h3 id="题目：通过反射将Map转换成JavaBean的工具类方法"><a href="#题目：通过反射将Map转换成JavaBean的工具类方法" class="headerlink" title="题目：通过反射将Map转换成JavaBean的工具类方法"></a>题目：通过反射将Map转换成JavaBean的工具类方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Object <span class="title">mapToObject</span><span class="params">(Map&lt;String, Object&gt; map, Class&lt;?&gt; beanClass)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (map == <span class="keyword">null</span>)</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    Object obj = <span class="keyword">null</span>;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        obj = beanClass.newInstance();</span><br><span class="line">        Field[] fields = obj.getClass().getDeclaredFields();</span><br><span class="line">        <span class="keyword">for</span> (Field field : fields) &#123;</span><br><span class="line">            <span class="keyword">int</span> mod = field.getModifiers();</span><br><span class="line">            <span class="keyword">if</span>(Modifier.isStatic(mod) || Modifier.isFinal(mod))&#123;</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            field.setAccessible(<span class="keyword">true</span>);</span><br><span class="line">            field.set(obj, map.get(field.getName()));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">        e.printStackTrace();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> obj;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="Servlet"><a href="#Servlet" class="headerlink" title="Servlet"></a>Servlet</h2><h3 id="生命周期"><a href="#生命周期" class="headerlink" title="生命周期"></a>生命周期</h3><p>初始化阶段：读取配置文件信息，构造Servlet对象，创建ServletConfig对象</p>
<ol>
<li>Servlet 初始化后调用 init (ServletConfig) 方法。</li>
<li>Servlet 调用 service() 方法来处理客户端的请求。</li>
<li>Servlet 销毁前调用 destroy() 方法。</li>
<li>Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。</li>
</ol>
<h2 id="设计模式"><a href="#设计模式" class="headerlink" title="设计模式"></a>设计模式</h2><h3 id="单例模式"><a href="#单例模式" class="headerlink" title="单例模式"></a>单例模式</h3><ul>
<li>饿汉式：类初始化时直接创建对象，无线程安全问题</li>
<li>懒汉式：延迟创建对象</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Singleton</span></span>&#123;</span><br><span class="line">    <span class="comment">//构造器私有化</span></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">Singleton</span><span class="params">()</span></span>&#123;&#125;</span><br><span class="line">    <span class="comment">//饿汉式</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">private</span> Singleton instance=<span class="keyword">new</span> Singleton();<span class="comment">//因为无法实例化，所以必须是静态的</span></span><br><span class="line">    <span class="function"><span class="keyword">static</span> <span class="keyword">public</span> Singleton <span class="title">getInstance</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> instance;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//懒汉线程安全</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">volatile</span> Singleton instance2;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Singleton <span class="title">getInstance2</span><span class="params">()</span></span>&#123;<span class="comment">//双锁检查，线程安全</span></span><br><span class="line">        <span class="keyword">if</span>(instance2==<span class="keyword">null</span>)&#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (Singleton.class)&#123;</span><br><span class="line">                <span class="keyword">if</span>(instance2==<span class="keyword">null</span>)</span><br><span class="line">                    instance2=<span class="keyword">new</span> Singleton();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> instance2;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//懒汉2：静态内部类获取</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Singleton2</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="title">Singleton2</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//通过方法获取该静态实例</span></span><br><span class="line">    <span class="comment">//加载内部类才创建INSTANCE对象</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">Inner</span> </span>&#123;</span><br><span class="line">        <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> Singleton2 INSTANCE = <span class="keyword">new</span> Singleton2();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Singleton2 <span class="title">getInstance</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">//此处才创建INSTANCE</span></span><br><span class="line">        <span class="keyword">return</span> Inner.INSTANCE;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>创建对象步骤：<ol>
<li>memory = allocate(); //分配内存空间（留位置给新同学）</li>
<li>instance(memory); //初始化对象（新同学到达）</li>
<li>instance = memory; //设置instance指向该内存地址，instance!=null（看向该位置）<br>由于2和3没有数据依赖关系，多线程下可被重排，instance!=null，但是对象还未初始化完成！因此需加volatile禁止指令重排</li>
</ol>
</li>
</ul>
<h2 id="其他知识点"><a href="#其他知识点" class="headerlink" title="其他知识点"></a>其他知识点</h2><p>&amp;&amp;是短路与，username != null &amp;&amp;!username.equals(“”);</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  


  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">余振鑫</p>
  <div class="site-description" itemprop="description">余振鑫的个人博客</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">9</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
  </nav>
</div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">余振鑫</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://muse.theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Muse</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/muse.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

</body>
</html>
